/**
 * 判断是否是数组
 * @param argument
 * @param {number|boolean} opt 是否用严格模式
 * @return {*}
 */
function is_array(argument, opt) {
    if (opt === 1 || opt === true) {
        return Object.prototype.toString.call(argument) === "[object Array]";
    }
    return argument && (typeof argument === "object") && ("length" in argument) && (typeof argument.length === "number");
}

/**
 * 判断是否是对象
 * @param argument
 * @return {*}
 */
function is_object(argument) {
    if (argument && (typeof argument === "object") && ("length" in argument)) {
        return Object.prototype.toString.call(argument) === "[object Object]";
    }
    return argument && (typeof argument === "object") && !("length" in argument);
}

/**
 * 判断是否是函数
 * @param argument
 * @return {*|boolean}
 */
function is_function(argument) {
    return typeof argument === "function";
}

/**
 * 判断是否是字符串
 * @param argument
 * @return {*|boolean}
 */
function is_string(argument) {
    return typeof argument === "string";
}

/**
 * 判断是否是布尔值
 * @param argument
 * @return {boolean}
 */
function is_boolean(argument) {
    return typeof argument === "boolean";
}

/**
 * 判断是否是数字
 * @param argument
 * @return {boolean}
 */
function is_number(argument) {
    return typeof argument === "number";
}

/**
 * 判断是否是未定义
 * @param argument
 * @return {boolean}
 */
function is_undefined(argument) {
    return typeof argument === "undefined";
}

/**
 * 判断是否是空值
 * @param argument
 * @return {boolean}
 */
function is_null(argument) {
    return argument === null || argument === "";
}

/**
 * 是否存在[true存在，false不存在]
 * @param argument
 * @param {array} opt 这里面的值是代表“不存在”
 * @return {boolean}
 */
function is_exist(argument, opt) {
    opt || (opt = ["", null, false, undefined]);
    for (var k in opt) {
        if (opt[k] === argument) {
            return false;
        }
    }
    return true;
}

/**
 * 判断是否是整数
 * @param vars
 * @return {boolean}
 */
function is_int(vars) {
    return /^[-]{0,1}\d+$/i.test(vars + "");
}

/**
 * 判断是否是小数
 * @param vars
 * @return {boolean}
 */
function is_float(vars) {
    return /^[-]{0,1}[0-9]+\.{0,1}[0-9]*$/i.test(vars + "")
}

/**
 * 是否是html标签元素
 * @param argument
 * @returns {boolean}
 */
function is_element(argument) {
    var reg = /^(\[object HTML[A-Za-z\-_\.]*Element\])$/i;
    return reg.test(Object.prototype.toString.call(argument));
}

/**
 * 是否是 symbol 类型
 * @param argument
 * @return {boolean}
 */
function is_symbol(argument) {
    return typeof argument === "symbol";
}

/**
 * 是否是文件对象
 * @param argument
 * @returns {boolean}
 */
function is_file(argument) {
    return Object.prototype.toString.call(argument) === "[object File]";
}

/**
 * 是否是字符串（扩大范围）
 * @param {string|number} str
 * @returns {boolean|(*|boolean)}
 */
function y_string(str) {
    return is_exist(str) && (is_string(str) || is_number(str));
}

/**
 * 遍历数组或对象
 * @param {array|object} obj
 * @param {function} fn 这个回调函数传入2个参数 key,value，返回值为0的时候停止遍历
 */
function foreach(obj, fn) {
    if (typeof fn === "function") {
        if (is_array(obj, 1)) {
            for (var i = 0, len = obj.length; i < len; i++) {
                //console.log(i);
                if (fn.call(obj, i, obj[i]) === 0) {
                    break;
                }
            }
        }
        if (is_object(obj)) {
            for (var attr in obj) {
                if (fn.call(obj, attr, obj[attr]) === 0) {
                    break;
                }
            }
        }
    }
}

/**
 * 遍历数组或对象（Object原型链上）
 * @param {function} fn 传入两个参数:key,value。返回值为0或false时停止循环遍历
 */
Object.prototype.foreach = function (fn) {
    if (typeof fn === "function") {
        var rv;
        if (is_array(this, 1)) {
            for (var i = 0, len = this.length; i < len; i++) {
                rv = fn.call(this, i, this[i]);
                if (rv === 0 || rv === false) {
                    break;
                }
            }
        }
        if (is_object(this) || is_function(this)) {
            for (var attr in this) {
                rv = fn.call(this, attr, this[attr]);
                if (rv === 0 || rv === false) {
                    break;
                }
            }
        }
    }
};

/**
 * 遍历对象属性(对象，数组，函数)
 * @param {function} fn
 */
Object.prototype.foreachAll = function (fn) {
    if (typeof fn === "function") {
        var list = ["[object Storage]", "[object Window]", "[object Function]"], rv;
        if (is_object(this) || is_array(this, 1) || is_function(this) || in_array(Object.prototype.toString.call(this), list, true)) {
            for (var attr in this) {
                rv = fn.call(this, attr, this[attr]);
                if (rv === 0 || rv === false) {
                    break;
                }
            }
        }
    }
};

/**
 * 生成随机数
 * @param {number} start_num
 * @param {number} end_num
 * @return {number}
 */
function random(start_num, end_num) {
    (typeof start_num === "number") || (start_num = 0);
    (typeof end_num === "number") || (end_num = 10);
    return ~~(Math.random() * (end_num - start_num + 1)) + ~~(start_num);
}

/**
 * 生成随机字符串
 * @param {number} l 生成的字符串长度
 * @param {string} opt 选项，如字符串里面只含有数字那么值为 n
 * @param {object} obj
 * @return {string}
 */
function randomString(l, opt, obj) {
    var n = "0123456789", s = "abcdefghijklmnopqrstuvwxyz", S = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", str = "", C = {
        /*数字*/
        n: n,
        /*小写字母*/
        s: s,
        /*大写字母*/
        S: S,
        /*数字和小写字母*/
        ns: n + s,
        /*数字和大写字母*/
        nS: n + S,
        /*小写字母和大写字母*/
        sS: s + S,
        /*数字和小写字母和大写字母*/
        nsS: n + s + S,
        /*十六进制字符串*/
        hex: "0123456789abcdef",
        /*其他字符包括数字小写和大写*/
        all: n + s + S + "_+-*=^~,#$@|!"
    };
    (opt) || (opt = "n");
    if (is_object(obj)) {
        for (var attr in obj) {
            C[attr] = obj[attr];
        }
    }
    for (var i = 0, str_len = C[opt].length; i < l; i++) {
        str += C[opt][~~(Math.random() * str_len)];
    }
    return str;
}

/**
 * 设置对象属性
 * @param {object|array} obj
 * @param {object} data
 */
function set_obj_attr(obj, data) {
    if ((is_object(obj) || is_array(obj)) && is_object(data)) {
        for (var attr in data) {
            is_object(data[attr]) ? set_obj_attr(obj[attr] = is_object(obj[attr]) || is_array(obj[attr]) ? obj[attr] : {}, data[attr]) : obj[attr] = data[attr];
        }
    }
}

/**
 * unicode字符编码
 * @param strings
 * @return {*}
 */
function enUnicode(strings) {
    var unicode_str = "";
    if (strings) {
        for (var i = 0, len = strings.length; i < len; i++) {
            var s = "00" + strings.charCodeAt(i).toString(16);
            /*截取后面4个字符串*/
            s = s.slice(-4);
            unicode_str += "\\u" + s;
        }
        return unicode_str;
    }
    else {
        return false;
    }
}

/**
 * 解码unicode编码字符串
 * @param strings
 * @return {string}
 */
function deUnicode(strings) {
    strings = strings.replace(/\\/g, "%");
    //console.log(strings);
    return unescape(strings);
    /*return decodeURIComponent(strings);*/
}

/**
 * 复制内容到剪切板
 * @param {string} text
 * @returns {HTMLElement[]}
 */
function copyText(text) {
    var E = document.createElement("textarea");
    E.value = text;
    E.setAttribute("style", "position: fixed; top: 0px; left: -1920px;");
    document.body.appendChild(E);
    /*var currentFocus = document.activeElement;*/
    E.focus();
    /*全选对象里面的内容，跟 E.select()一样*/
    E.setSelectionRange(0, E.value.length);
    /*复制选中的文字到剪贴板*/
    document.execCommand('copy', true);
    E.focus();
    /*currentFocus.focus();*/
    document.body.removeChild(E);
    return [E];
}

/**
 * 本地缓存(localStorage或sessionStorage)操作,sessionStorage是关闭当前页面数据就清空 【构造函数】
 * @param{string} name 值为(localStorage|sessionStorage),默认localStorage
 */
function storage(name) {
    (name) || (name = "localStorage");
    this._Storage = window[name];
    /* this._Storage=localStorage; 或 this._Storage=sessionStorage;*/
    /**
     * 添加或修改localStorage对象或者sessionStorage的属性(键名)内容
     * @param {string} key 键名(对象属性)
     * @param {string|array|object} value 添加或修改的数据
     * @param {boolean} is_encode 是否给字符串编码
     * @returns {storage}
     */
    this.set = function (key, value, is_encode) {
        /*默认给字符串编码*/
        if (!key) {
            return;
        }
        if (is_object(value) || is_array(value)) {
            this._Storage.setItem(key, is_encode ? encodeURIComponent(JSON.stringify(value)) : JSON.stringify(value));
            /*或者这样写: this._Storage[key]= is_encode ? JSON.stringify(value) : encodeURIComponent(JSON.stringify(value)); */
        }
        else {
            this._Storage.setItem(key, is_encode ? encodeURIComponent(value) : value);
        }
        return this;
    };
    /**
     * 获取localStorage对象或者sessionStorage对象的属性(键名)内容
     * @param {string} key
     * @param {boolean} decode 是否给字符串解码
     * @returns {*}
     */
    this.get = function (key, decode) {
        if (!key) {
            return this._Storage;
        }
        var copy = "", data = "";
        copy = data = decode ? decodeURIComponent(this._Storage.getItem(key)) : this._Storage.getItem(key);
        /*或者这样写: var data= decode ? this._Storage[key] : decodeURIComponent(this._Storage[key]); */
        try {
            data = JSON.parse(data);
        }
        catch (error) {
            console.log("错误！" + error.message);
        }
        return is_object(data) || is_array(data) ? data : copy;
    };
    /**
     * 移除localStorage对象或者sessionStorage对象的属性(键名)内容
     * @param {string} key
     * @param {boolean} mode 是否移除全部属性
     * @returns {storage}
     */
    this.remove = function (key, mode) {
        /*默认移除指定的localStorage或sessionStorage内容*/
        (key) || (mode = true);
        mode ? this._Storage.clear() : this._Storage.removeItem(key);
        return this;
    };
    /**
     * 遍历localStorage对象或者sessionStorage对象的属性(键名)内容
     * @param {function} fun 回调函数，传入2个参数【@key (键名),@value (键值)】
     * @returns {storage}
     */
    this.foreach = function (fun) {
        for (var i = 0, len = this._Storage.length; i < len; i++) {
            var key = this._Storage.key(i);
            var value = this.get(key);
            is_function(fun) && fun.call(this, key, value);
        }
        return this;
    };
}

/**
 * 重构二维数组数据
 * @param {array|object} lv2_data 二维数组及多维数组
 * @param {string} field 设置某个字段的值为数组下标
 * @returns {boolean|object}
 */
function reconfig_array(lv2_data, field) {
    var temp = false, k, v;
    if ((is_array(lv2_data) || is_object(lv2_data)) && y_string(field)) {
        temp = {};
        for (k in lv2_data) {
            v = lv2_data[k];
            if (is_object(v) && y_string(v[field])) {
                temp[v[field]] = v;
            }
        }
    }
    return temp;
}

/**
 * 删除左右两端的空格
 * @param {string} str
 * @param {string} preg
 * @returns {void | string | *}
 */
function trim(str, preg) {
    if (preg) {
        preg = new RegExp("(^" + preg + "*|" + preg + "*$)", "ig");
    }
    (preg) || (preg = /(^[\s\t\r\n]*|[\s\t\r\n]*$)/ig);
    return str.replace(preg, "");
}

/**
 * 删除左侧的空格
 * @param {string} str
 * @param {string} preg
 * @returns {void | string | *}
 */
function ltrim(str, preg) {
    if (preg) {
        preg = new RegExp("(^" + preg + "*)", "ig");
    }
    (preg) || (preg = /(^[\s\t\r\n]*)/i);
    return str.replace(preg, "");
}

/**
 * 删除右侧的空格
 * @param {string} str
 * @param {string} preg
 * @returns {void | string | *}
 */
function rtrim(str, preg) {
    if (preg) {
        preg = new RegExp("(" + preg + "*$)", "ig");
    }
    (preg) || (preg = /([\s\t\r\n]*$)/i);
    return str.replace(preg, "");
}

/**
 * 搜索数组中是否存在指定的值
 * @param {string} needle
 * @param {array} haystack
 * @param {boolean} argStrict
 * @return {boolean}
 */
function in_array(needle, haystack, argStrict) {
    var key = "", strict = !!argStrict;
    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) {
                return true
            }
        }
    } else {
        for (key in haystack) {
            if (haystack[key] == needle) {
                return true
            }
        }
    }
    return false
}



/**
 * 10位时间戳
 * @returns {number}
 */
function time() {
    return Math.floor(new Date().getTime() / 1000);
}

/**
 * 日期字符串格式转换为时间戳
 * @param {string} text
 * @param  now
 * @returns {*}
 */
function strtotime(text,now){var parsed,match,today,year,date,days,ranges,len,times,regex,i,fail=false;if(!text){return fail}text=text.replace(/^\s+|\s+$/g,"").replace(/\s{2,}/g," ").replace(/[\t\r\n]/g,"").toLowerCase();match=text.match(/^(\d{1,4})([\-\.\/\:])(\d{1,2})([\-\.\/\:])(\d{1,4})(?:\s(\d{1,2}):(\d{2})?:?(\d{2})?)?(?:\s([A-Z]+)?)?$/);if(match&&match[2]===match[4]){if(match[1]>1901){switch(match[2]){case"-":if(match[3]>12||match[5]>31){return fail}return new Date(match[1],parseInt(match[3],10)-1,match[5],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000;case".":return fail;case"/":if(match[3]>12||match[5]>31){return fail}return new Date(match[1],parseInt(match[3],10)-1,match[5],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000}}else{if(match[5]>1901){switch(match[2]){case"-":if(match[3]>12||match[1]>31){return fail}return new Date(match[5],parseInt(match[3],10)-1,match[1],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000;case".":if(match[3]>12||match[1]>31){return fail}return new Date(match[5],parseInt(match[3],10)-1,match[1],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000;case"/":if(match[1]>12||match[3]>31){return fail}return new Date(match[5],parseInt(match[1],10)-1,match[3],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000}}else{switch(match[2]){case"-":if(match[3]>12||match[5]>31||(match[1]<70&&match[1]>38)){return fail}year=match[1]>=0&&match[1]<=38?+match[1]+2000:match[1];return new Date(year,parseInt(match[3],10)-1,match[5],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000;case".":if(match[5]>=70){if(match[3]>12||match[1]>31){return fail}return new Date(match[5],parseInt(match[3],10)-1,match[1],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000}if(match[5]<60&&!match[6]){if(match[1]>23||match[3]>59){return fail}today=new Date();return new Date(today.getFullYear(),today.getMonth(),today.getDate(),match[1]||0,match[3]||0,match[5]||0,match[9]||0)/1000}return fail;case"/":if(match[1]>12||match[3]>31||(match[5]<70&&match[5]>38)){return fail}year=match[5]>=0&&match[5]<=38?+match[5]+2000:match[5];return new Date(year,parseInt(match[1],10)-1,match[3],match[6]||0,match[7]||0,match[8]||0,match[9]||0)/1000;case":":if(match[1]>23||match[3]>59||match[5]>59){return fail}today=new Date();return new Date(today.getFullYear(),today.getMonth(),today.getDate(),match[1]||0,match[3]||0,match[5]||0)/1000}}}}if(text==="now"){return now===null||isNaN(now)?new Date().getTime()/1000|0:now|0}if(!isNaN(parsed=Date.parse(text))){return parsed/1000|0}date=now?new Date(now*1000):new Date();days={"sun":0,"mon":1,"tue":2,"wed":3,"thu":4,"fri":5,"sat":6};ranges={"yea":"FullYear","mon":"Month","day":"Date","hou":"Hours","min":"Minutes","sec":"Seconds"};function lastNext(type,range,modifier){var diff,day=days[range];if(typeof day!=="undefined"){diff=day-date.getDay();if(diff===0){diff=7*modifier}else{if(diff>0&&type==="last"){diff-=7}else{if(diff<0&&type==="next"){diff+=7}}}date.setDate(date.getDate()+diff)}}function process(val){var splt=val.split(" "),type=splt[0],range=splt[1].substring(0,3),typeIsNumber=/\d+/.test(type),ago=splt[2]==="ago",num=(type==="last"?-1:1)*(ago?-1:1);if(typeIsNumber){num*=parseInt(type,10)}if(ranges.hasOwnProperty(range)&&!splt[1].match(/^mon(day|\.)?$/i)){return date["set"+ranges[range]](date["get"+ranges[range]]()+num)}if(range==="wee"){return date.setDate(date.getDate()+(num*7))}if(type==="next"||type==="last"){lastNext(type,range,num)}else{if(!typeIsNumber){return false}}return true}times="(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec"+"|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?"+"|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)";regex="([+-]?\\d+\\s"+times+"|"+"(last|next)\\s"+times+")(\\sago)?";match=text.match(new RegExp(regex,"gi"));if(!match){return fail}for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}return(date.getTime()/1000)}

/**
 * 返回自定义日期字符串
 * @param {string} format 日期字符串格式如： Y-m-d H:i:s。必填
 * @param {number} timestamp 时间戳
 * @returns {*}
 */
function date(format,timestamp){var that=this;var jsdate,f;var txt_words=["Sun","Mon","Tues","Wednes","Thurs","Fri","Satur","January","February","March","April","May","June","July","August","September","October","November","December"];var formatChr=/\\?(.?)/gi;var formatChrCb=function(t,s){return f[t]?f[t]():s};var _pad=function(n,c){n=String(n);while(n.length<c){n="0"+n}return n};f={d:function(){return _pad(f.j(),2)},D:function(){return f.l().slice(0,3)},j:function(){return jsdate.getDate()},l:function(){return txt_words[f.w()]+"day"},N:function(){return f.w()||7},S:function(){var j=f.j();var i=j%10;if(i<=3&&parseInt((j%100)/10,10)==1){i=0}return["st","nd","rd"][i-1]||"th"},w:function(){return jsdate.getDay()},z:function(){var a=new Date(f.Y(),f.n()-1,f.j());var b=new Date(f.Y(),0,1);return Math.round((a-b)/86400000)},W:function(){var a=new Date(f.Y(),f.n()-1,f.j()-f.N()+3);var b=new Date(a.getFullYear(),0,4);return _pad(1+Math.round((a-b)/86400000/7),2)},F:function(){return txt_words[6+f.n()]},m:function(){return _pad(f.n(),2)},M:function(){return f.F().slice(0,3)},n:function(){return jsdate.getMonth()+1},t:function(){return(new Date(f.Y(),f.n(),0)).getDate()},L:function(){var j=f.Y();return j%4===0&j%100!==0|j%400===0},o:function(){var n=f.n();var W=f.W();var Y=f.Y();return Y+(n===12&&W<9?1:n===1&&W>9?-1:0)},Y:function(){return jsdate.getFullYear()},y:function(){return f.Y().toString().slice(-2)},a:function(){return jsdate.getHours()>11?"pm":"am"},A:function(){return f.a().toUpperCase()},B:function(){var H=jsdate.getUTCHours()*3600;var i=jsdate.getUTCMinutes()*60;var s=jsdate.getUTCSeconds();return _pad(Math.floor((H+i+s+3600)/86.4)%1000,3)},g:function(){return f.G()%12||12},G:function(){return jsdate.getHours()},h:function(){return _pad(f.g(),2)},H:function(){return _pad(f.G(),2)},i:function(){return _pad(jsdate.getMinutes(),2)},s:function(){return _pad(jsdate.getSeconds(),2)},u:function(){return _pad(jsdate.getMilliseconds()*1000,6)},e:function(){throw"Not supported (see source code of date() for timezone on how to add support)"},I:function(){var a=new Date(f.Y(),0);var c=Date.UTC(f.Y(),0);var b=new Date(f.Y(),6);var d=Date.UTC(f.Y(),6);return((a-c)!==(b-d))?1:0},O:function(){var tzo=jsdate.getTimezoneOffset();var a=Math.abs(tzo);return(tzo>0?"-":"+")+_pad(Math.floor(a/60)*100+a%60,4)},P:function(){var O=f.O();return(O.substr(0,3)+":"+O.substr(3,2))},T:function(){return"UTC"},Z:function(){return -jsdate.getTimezoneOffset()*60},c:function(){return"Y-m-d\\TH:i:sP".replace(formatChr,formatChrCb)},r:function(){return"D, d M Y H:i:s O".replace(formatChr,formatChrCb)},U:function(){return jsdate/1000|0}};this.date=function(format,timestamp){that=this;jsdate=(timestamp===undefined?new Date():(timestamp instanceof Date)?new Date(timestamp):new Date(timestamp*1000));return format.replace(formatChr,formatChrCb)};return this.date(format,timestamp)}


/**
 * URL编码
 * @param str
 * @returns {string}
 */
function urlencode(str) {
    str = (str + "").toString();
    return encodeURIComponent(str).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A").replace(/%20/g, "+")
}

/**
 * URL解码
 * @param str
 * @returns {string}
 */
function urldecode(str) {
    return decodeURIComponent((str + "").replace(/%(?![\da-f]{2})/gi, function () {
        return "%25"
    }).replace(/\+/g, "%20"));
}

function utf8_encode(argString){if(argString===null||typeof argString==="undefined"){return""}var string=(argString+"");var utftext="",start,end,stringl=0;start=end=0;stringl=string.length;for(var n=0;n<stringl;n++){var c1=string.charCodeAt(n);var enc=null;if(c1<128){end++}else{if(c1>127&&c1<2048){enc=String.fromCharCode((c1>>6)|192,(c1&63)|128)}else{if((c1&63488)!=55296){enc=String.fromCharCode((c1>>12)|224,((c1>>6)&63)|128,(c1&63)|128)}else{if((c1&64512)!=55296){throw new RangeError("Unmatched trail surrogate at "+n)}var c2=string.charCodeAt(++n);if((c2&64512)!=56320){throw new RangeError("Unmatched lead surrogate at "+(n-1))}c1=((c1&1023)<<10)+(c2&1023)+65536;enc=String.fromCharCode((c1>>18)|240,((c1>>12)&63)|128,((c1>>6)&63)|128,(c1&63)|128)}}}if(enc!==null){if(end>start){utftext+=string.slice(start,end)}utftext+=enc;start=end=n+1}}if(end>start){utftext+=string.slice(start,stringl)}return utftext}
function utf8_decode(str_data){var tmp_arr=[],i=0,c1=0,seqlen=0;str_data+="";while(i<str_data.length){c1=str_data.charCodeAt(i)&255;seqlen=0;if(c1<=191){c1=(c1&127);seqlen=1}else{if(c1<=223){c1=(c1&31);seqlen=2}else{if(c1<=239){c1=(c1&15);seqlen=3}else{c1=(c1&7);seqlen=4}}}for(var ai=1;ai<seqlen;++ai){c1=((c1<<6)|(str_data.charCodeAt(ai+i)&63))}if(seqlen==4){c1-=65536;tmp_arr.push(String.fromCharCode(55296|((c1>>10)&1023)),String.fromCharCode(56320|(c1&1023)))}else{tmp_arr.push(String.fromCharCode(c1))}i+=seqlen}return tmp_arr.join("")}
function strtolower(str){return(str+"").toLowerCase()}
function strtoupper(str){return(str+"").toUpperCase()}
function strtr (str, trFrom, trTo) {var fr = ''; var i = 0; var j = 0; var lenStr = 0; var lenFrom = 0; var sortByReference = false; var fromTypeStr = ''; var toTypeStr = ''; var istr = ''; var tmpFrom = []; var tmpTo = []; var ret = ''; var match = false; /*Walk through subject and replace chars when needed*/ lenStr = str.length; lenFrom = trFrom.length; fromTypeStr = typeof trFrom === 'string'; toTypeStr = typeof trTo === 'string'; for (i = 0; i < lenStr; i++) {match = false; if (fromTypeStr) {istr = str.charAt(i); for (j = 0; j < lenFrom; j++) {if (istr === trFrom.charAt(j)) {match = true; break; } } } else {for (j = 0; j < lenFrom; j++) {if (str.substr(i, trFrom[j].length) === trFrom[j]) {match = true; /*Fast forward*/ i = (i + trFrom[j].length) - 1; break; } } } if (match) {ret += toTypeStr ? trTo.charAt(j) : trTo[j]; } else {ret += str.charAt(i); } } return ret; }
function str_pad (input, padLength, padString, padType) {var half = ''; var padToGo; var _strPadRepeater = function (s, len) {var collect = ''; while (collect.length < len) {collect += s; } collect = collect.substr(0, len); return collect; }; input += ''; padString = padString !== undefined ? padString : ' '; if (padType !== 'STR_PAD_LEFT' && padType !== 'STR_PAD_RIGHT' && padType !== 'STR_PAD_BOTH') {padType = 'STR_PAD_RIGHT'; } if ((padToGo = padLength - input.length) > 0) {if (padType === 'STR_PAD_LEFT') {input = _strPadRepeater(padString, padToGo) + input; } else if (padType === 'STR_PAD_RIGHT') {input = input + _strPadRepeater(padString, padToGo); } else if (padType === 'STR_PAD_BOTH') {half = _strPadRepeater(padString, Math.ceil(padToGo / 2)); input = half + input + half; input = input.substr(0, padLength); } } return input; }
function strlen(str){var bytes=0,i=0;for(;i<str.length;++i,++bytes){if(str.charCodeAt(i)>255){++bytes}}return bytes}

/**
 * base64编码
 * @param {string} data
 * @returns {*}
 */
function base64_encode(data){var b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var o1,o2,o3,h1,h2,h3,h4,bits,i=0,ac=0,enc="",tmp_arr=[];if(!data){return data}data=unescape(encodeURIComponent(data));do{o1=data.charCodeAt(i++);o2=data.charCodeAt(i++);o3=data.charCodeAt(i++);bits=o1<<16|o2<<8|o3;h1=bits>>18&63;h2=bits>>12&63;h3=bits>>6&63;h4=bits&63;tmp_arr[ac++]=b64.charAt(h1)+b64.charAt(h2)+b64.charAt(h3)+b64.charAt(h4)}while(i<data.length);enc=tmp_arr.join("");var r=data.length%3;return(r?enc.slice(0,r-3):enc)+"===".slice(r||3)};

/**
 * base64解码
 * @param {string} data
 * @returns {*}
 */
function base64_decode(data){var b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var o1,o2,o3,h1,h2,h3,h4,bits,i=0,ac=0,dec="",tmp_arr=[];if(!data){return data}data+="";do{h1=b64.indexOf(data.charAt(i++));h2=b64.indexOf(data.charAt(i++));h3=b64.indexOf(data.charAt(i++));h4=b64.indexOf(data.charAt(i++));bits=h1<<18|h2<<12|h3<<6|h4;o1=bits>>16&255;o2=bits>>8&255;o3=bits&255;if(h3==64){tmp_arr[ac++]=String.fromCharCode(o1)}else{if(h4==64){tmp_arr[ac++]=String.fromCharCode(o1,o2)}else{tmp_arr[ac++]=String.fromCharCode(o1,o2,o3)}}}while(i<data.length);dec=tmp_arr.join("");return decodeURIComponent(escape(dec.replace(/\0+$/,"")))};

/**
 * md5字符串加密
 * @param {string} C
 * @returns {string}
 */
function md5(C){var D;var w=function(b,a){return(b<<a)|(b>>>(32-a))};var H=function(k,b){var V,a,d,x,c;d=(k&2147483648);x=(b&2147483648);V=(k&1073741824);a=(b&1073741824);c=(k&1073741823)+(b&1073741823);if(V&a){return(c^2147483648^d^x)}if(V|a){if(c&1073741824){return(c^3221225472^d^x)}else{return(c^1073741824^d^x)}}else{return(c^d^x)}};var r=function(a,c,b){return(a&c)|((~a)&b)};var q=function(a,c,b){return(a&b)|(c&(~b))};var p=function(a,c,b){return(a^c^b)};var n=function(a,c,b){return(c^(a|(~b)))};var u=function(W,V,aa,Z,k,X,Y){W=H(W,H(H(r(V,aa,Z),k),Y));return H(w(W,X),V)};var f=function(W,V,aa,Z,k,X,Y){W=H(W,H(H(q(V,aa,Z),k),Y));return H(w(W,X),V)};var F=function(W,V,aa,Z,k,X,Y){W=H(W,H(H(p(V,aa,Z),k),Y));return H(w(W,X),V)};var t=function(W,V,aa,Z,k,X,Y){W=H(W,H(H(n(V,aa,Z),k),Y));return H(w(W,X),V)};var e=function(V){var W;var d=V.length;var c=d+8;var b=(c-(c%64))/64;var x=(b+1)*16;var X=new Array(x-1);var a=0;var k=0;while(k<d){W=(k-(k%4))/4;a=(k%4)*8;X[W]=(X[W]|(V.charCodeAt(k)<<a));k++}W=(k-(k%4))/4;a=(k%4)*8;X[W]=X[W]|(128<<a);X[x-2]=d<<3;X[x-1]=d>>>29;return X};var s=function(d){var a="",b="",k,c;for(c=0;c<=3;c++){k=(d>>>(c*8))&255;b="0"+k.toString(16);a=a+b.substr(b.length-2,2)}return a};var E=[],L,h,G,v,g,U,T,S,R,O=7,M=12,J=17,I=22,B=5,A=9,z=14,y=20,o=4,m=11,l=16,j=23,Q=6,P=10,N=15,K=21;C=this.utf8_encode(C);E=e(C);U=1732584193;T=4023233417;S=2562383102;R=271733878;D=E.length;for(L=0;L<D;L+=16){h=U;G=T;v=S;g=R;U=u(U,T,S,R,E[L+0],O,3614090360);R=u(R,U,T,S,E[L+1],M,3905402710);S=u(S,R,U,T,E[L+2],J,606105819);T=u(T,S,R,U,E[L+3],I,3250441966);U=u(U,T,S,R,E[L+4],O,4118548399);R=u(R,U,T,S,E[L+5],M,1200080426);S=u(S,R,U,T,E[L+6],J,2821735955);T=u(T,S,R,U,E[L+7],I,4249261313);U=u(U,T,S,R,E[L+8],O,1770035416);R=u(R,U,T,S,E[L+9],M,2336552879);S=u(S,R,U,T,E[L+10],J,4294925233);T=u(T,S,R,U,E[L+11],I,2304563134);U=u(U,T,S,R,E[L+12],O,1804603682);R=u(R,U,T,S,E[L+13],M,4254626195);S=u(S,R,U,T,E[L+14],J,2792965006);T=u(T,S,R,U,E[L+15],I,1236535329);U=f(U,T,S,R,E[L+1],B,4129170786);R=f(R,U,T,S,E[L+6],A,3225465664);S=f(S,R,U,T,E[L+11],z,643717713);T=f(T,S,R,U,E[L+0],y,3921069994);U=f(U,T,S,R,E[L+5],B,3593408605);R=f(R,U,T,S,E[L+10],A,38016083);S=f(S,R,U,T,E[L+15],z,3634488961);T=f(T,S,R,U,E[L+4],y,3889429448);U=f(U,T,S,R,E[L+9],B,568446438);R=f(R,U,T,S,E[L+14],A,3275163606);S=f(S,R,U,T,E[L+3],z,4107603335);T=f(T,S,R,U,E[L+8],y,1163531501);U=f(U,T,S,R,E[L+13],B,2850285829);R=f(R,U,T,S,E[L+2],A,4243563512);S=f(S,R,U,T,E[L+7],z,1735328473);T=f(T,S,R,U,E[L+12],y,2368359562);U=F(U,T,S,R,E[L+5],o,4294588738);R=F(R,U,T,S,E[L+8],m,2272392833);S=F(S,R,U,T,E[L+11],l,1839030562);T=F(T,S,R,U,E[L+14],j,4259657740);U=F(U,T,S,R,E[L+1],o,2763975236);R=F(R,U,T,S,E[L+4],m,1272893353);S=F(S,R,U,T,E[L+7],l,4139469664);T=F(T,S,R,U,E[L+10],j,3200236656);U=F(U,T,S,R,E[L+13],o,681279174);R=F(R,U,T,S,E[L+0],m,3936430074);S=F(S,R,U,T,E[L+3],l,3572445317);T=F(T,S,R,U,E[L+6],j,76029189);U=F(U,T,S,R,E[L+9],o,3654602809);R=F(R,U,T,S,E[L+12],m,3873151461);S=F(S,R,U,T,E[L+15],l,530742520);T=F(T,S,R,U,E[L+2],j,3299628645);U=t(U,T,S,R,E[L+0],Q,4096336452);R=t(R,U,T,S,E[L+7],P,1126891415);S=t(S,R,U,T,E[L+14],N,2878612391);T=t(T,S,R,U,E[L+5],K,4237533241);U=t(U,T,S,R,E[L+12],Q,1700485571);R=t(R,U,T,S,E[L+3],P,2399980690);S=t(S,R,U,T,E[L+10],N,4293915773);T=t(T,S,R,U,E[L+1],K,2240044497);U=t(U,T,S,R,E[L+8],Q,1873313359);R=t(R,U,T,S,E[L+15],P,4264355552);S=t(S,R,U,T,E[L+6],N,2734768916);T=t(T,S,R,U,E[L+13],K,1309151649);U=t(U,T,S,R,E[L+4],Q,4149444226);R=t(R,U,T,S,E[L+11],P,3174756917);S=t(S,R,U,T,E[L+2],N,718787259);T=t(T,S,R,U,E[L+9],K,3951481745);U=H(U,h);T=H(T,G);S=H(S,v);R=H(R,g)}var i=s(U)+s(T)+s(S)+s(R);return i.toLowerCase()};

/**
 * 字符串格式化
 * @returns {*}
 */
function sprintf() {var regex = /%%|%(?:(\d+)\$)?((?:[-+#0 ]|'[\s\S])*)(\d+)?(?:\.(\d*))?([\s\S])/g; var args = arguments; var i = 0; var format = args[i++]; var _pad = function (str, len, chr, leftJustify) {if (!chr) {chr = ' '; } var padding = (str.length >= len) ? '' : new Array(1 + len - str.length >>> 0).join(chr); return leftJustify ? str + padding : padding + str; }; var justify = function (value, prefix, leftJustify, minWidth, padChar) {var diff = minWidth - value.length; if (diff > 0) {/*when padding with zeros on the left side keep sign (+ or -) in front*/ if (!leftJustify && padChar === '0') {value = [value.slice(0, prefix.length), _pad('', diff, '0', true), value.slice(prefix.length)].join(''); } else {value = _pad(value, minWidth, padChar, leftJustify); } } return value; }; var _formatBaseX = function (value, base, leftJustify, minWidth, precision, padChar) {/*Note: casts negative numbers to positive ones*/ var number = value >>> 0; value = _pad(number.toString(base), precision || 0, '0', false); return justify(value, '', leftJustify, minWidth, padChar); }; /*_formatString()*/ var _formatString = function (value, leftJustify, minWidth, precision, customPadChar) {if (precision !== null && precision !== undefined) {value = value.slice(0, precision); } return justify(value, '', leftJustify, minWidth, customPadChar); }; /* doFormat()*/ var doFormat = function (substring, argIndex, modifiers, minWidth, precision, specifier) {var number, prefix, method, textTransform, value; if (substring === '%%') {return '%'; } /* parse modifiers*/ var padChar = ' '; /*// pad with spaces by default*/ var leftJustify = false; var positiveNumberPrefix = ''; var j, l; for (j = 0, l = modifiers.length; j < l; j++) {switch (modifiers.charAt(j)) {case ' ': case '0': padChar = modifiers.charAt(j); break; case '+': positiveNumberPrefix = '+'; break; case '-': leftJustify = true; break; case "'": if (j + 1 < l) {padChar = modifiers.charAt(j + 1); j++; } break; } } if (!minWidth) {minWidth = 0; } else {minWidth = +minWidth; } if (!isFinite(minWidth)) {throw new Error('Width must be finite'); } if (!precision) {precision = (specifier === 'd') ? 0 : 'fFeE'.indexOf(specifier) > -1 ? 6 : undefined; } else {precision = +precision; } if (argIndex && +argIndex === 0) {throw new Error('Argument number must be greater than zero'); } if (argIndex && +argIndex >= args.length) {throw new Error('Too few arguments'); } value = argIndex ? args[+argIndex] : args[i++]; switch (specifier) {case '%': return '%'; case 's': return _formatString(value + '', leftJustify, minWidth, precision, padChar); case 'c': return _formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, padChar); case 'b': return _formatBaseX(value, 2, leftJustify, minWidth, precision, padChar); case 'o': return _formatBaseX(value, 8, leftJustify, minWidth, precision, padChar); case 'x': return _formatBaseX(value, 16, leftJustify, minWidth, precision, padChar); case 'X': return _formatBaseX(value, 16, leftJustify, minWidth, precision, padChar).toUpperCase(); case 'u': return _formatBaseX(value, 10, leftJustify, minWidth, precision, padChar); case 'i': case 'd': number = +value || 0; /*// Plain Math.round doesn't just truncate*/ number = Math.round(number - number % 1); prefix = number < 0 ? '-' : positiveNumberPrefix; value = prefix + _pad(String(Math.abs(number)), precision, '0', false); if (leftJustify && padChar === '0') {/*// can't right-pad 0s on integers*/ padChar = ' '; } return justify(value, prefix, leftJustify, minWidth, padChar); case 'e': case 'E': case 'f': /*// @todo: Should handle locales (as per setlocale)*/ case 'F': case 'g': case 'G': number = +value; prefix = number < 0 ? '-' : positiveNumberPrefix; method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(specifier.toLowerCase())]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(specifier) % 2]; value = prefix + Math.abs(number)[method](precision); return justify(value, prefix, leftJustify, minWidth, padChar)[textTransform](); default: /* unknown specifier, consume that char and return empty*/ return ''; } }; try {return format.replace(regex, doFormat); } catch (err) {return false; } }

/**
 * 解析php序列化字符串
 * @param {string} r
 * @returns {boolean|*|void}
 */
function unserialize(r){var t=function(){function r(r,t){var e=[];var n=true;var a=false;var o=undefined;try{for(var u=r[Symbol.iterator](),i;!(n=(i=u.next()).done);n=true){e.push(i.value);if(t&&e.length===t)break}}catch(r){a=true;o=r}finally{try{if(!n&&u["return"])u["return"]()}finally{if(a)throw o}}return e}return function(t,e){if(Array.isArray(t)){return t}else if(Symbol.iterator in Object(t)){return r(t,e)}else{throw new TypeError("Invalid attempt to destructure non-iterable instance")}}}();function e(){var r=[];var t=function t(e){r.push(e[0]);return e};t.get=function(t){if(t>=r.length){throw RangeError("Can't resolve reference "+(t+1))}return r[t]};return t}function n(r,t){var e=/^(?:N(?=;)|[bidsSaOCrR](?=:)|[^:]+(?=:))/g;var n=(e.exec(r)||[])[0];if(!n){throw SyntaxError("Invalid input: "+r)}switch(n){case"N":return t([null,2]);case"b":return t(a(r));case"i":return t(o(r));case"d":return t(u(r));case"s":return t(s(r));case"S":return t(c(r));case"a":return d(r,t);case"O":return f(r,t);case"C":return l(r,t);case"r":case"R":return h(r,t);default:throw SyntaxError("Invalid or unsupported data type: "+n)}}function a(r){var e=/^b:([01]);/;var n=e.exec(r)||[],a=t(n,2),o=a[0],u=a[1];if(!u){throw SyntaxError("Invalid bool value, expected 0 or 1")}return[u==="1",o.length]}function o(r){var e=/^i:([+-]?\d+);/;var n=e.exec(r)||[],a=t(n,2),o=a[0],u=a[1];if(!u){throw SyntaxError("Expected an integer value")}return[parseInt(u,10),o.length]}function u(r){var e=/^d:(NAN|-?INF|(?:\d+\.\d*|\d*\.\d+|\d+)(?:[eE][+-]\d+)?);/;var n=e.exec(r)||[],a=t(n,2),o=a[0],u=a[1];if(!u){throw SyntaxError("Expected a float value")}var i=void 0;switch(u){case"NAN":i=Number.NaN;break;case"-INF":i=Number.NEGATIVE_INFINITY;break;case"INF":i=Number.POSITIVE_INFINITY;break;default:i=parseFloat(u);break}return[i,o.length]}function i(r,t){var e=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var n=0;var a="";var o=0;var u=r.length;var i=false;var s=0;while(n<t&&o<u){var c=r.charAt(o);var v=c.charCodeAt(0);var f=v>=55296&&v<=56319;var l=v>=56320&&v<=57343;if(e&&c==="\\"){c=String.fromCharCode(parseInt(r.substr(o+1,2),16));s++;o+=2}o++;n+=f||l&&i?2:v>2047?3:v>127?2:1;n+=i&&!l?1:0;a+=c;i=f}return[a,n,s]}function s(r){var e=/^s:(\d+):"/g;var n=e.exec(r)||[],a=t(n,2),o=a[0],u=a[1];if(!o){throw SyntaxError("Expected a string value")}var s=parseInt(u,10);r=r.substr(o.length);var c=i(r,s),v=t(c,2),f=v[0],l=v[1];if(l!==s){throw SyntaxError("Expected string of "+s+" bytes, but got "+l)}r=r.substr(f.length);if(!r.startsWith('";')){throw SyntaxError('Expected ";')}return[f,o.length+f.length+2]}function c(r){var e=/^S:(\d+):"/g;var n=e.exec(r)||[],a=t(n,2),o=a[0],u=a[1];if(!o){throw SyntaxError("Expected an escaped string value")}var s=parseInt(u,10);r=r.substr(o.length);var c=i(r,s,true),v=t(c,3),f=v[0],l=v[1],h=v[2];if(l!==s){throw SyntaxError("Expected escaped string of "+s+" bytes, but got "+l)}r=r.substr(f.length+h*2);if(!r.startsWith('";')){throw SyntaxError('Expected ";')}return[f,o.length+f.length+2]}function v(r){try{return s(r)}catch(r){}try{return c(r)}catch(r){}try{return o(r)}catch(r){throw SyntaxError("Expected key or index")}}function f(r,e){var a=/^O:(\d+):"([^"]+)":(\d+):\{/;var o=a.exec(r)||[],u=t(o,4),i=u[0],s=u[2],c=u[3];if(!i){throw SyntaxError("Invalid input")}if(s!=="stdClass"){throw SyntaxError("Unsupported object type: "+s)}var f=i.length;var l=parseInt(c,10);var h={};e([h]);r=r.substr(f);for(var d=0;d<l;d++){var x=v(r);r=r.substr(x[1]);f+=x[1];var y=n(r,e);r=r.substr(y[1]);f+=y[1];h[x[0]]=y[0]}if(r.charAt(0)!=="}"){throw SyntaxError("Expected }")}return[h,f+1]}function l(r,t){throw Error("Not yet implemented")}function h(r,e){var n=/^[rR]:([1-9]\d*);/;var a=n.exec(r)||[],o=t(a,2),u=o[0],i=o[1];if(!u){throw SyntaxError("Expected reference value")}return[e.get(parseInt(i,10)-1),u.length]}function d(r,e){var n=/^a:(\d+):{/;var a=n.exec(r)||[],o=t(a,2),u=o[0],i=o[1];if(!i){throw SyntaxError("Expected array length annotation")}r=r.substr(u.length);var s=x(r,parseInt(i,10),e);if(r.charAt(s[1])!=="}"){throw SyntaxError("Expected }")}return[s[0],u.length+s[1]+1]}function x(r){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var e=arguments[2];var a=void 0;var o=false;var u=void 0;var i=0;var s=[];e([s]);for(var c=0;c<t;c++){a=v(r);if(!o){o=typeof a[0]==="string"}r=r.substr(a[1]);i+=a[1];u=n(r,e);r=r.substr(u[1]);i+=u[1];s[a[0]]=u[0]}if(o){s=Object.assign({},s)}return[s,i]}function y(r){try{if(typeof r!=="string"){return false}return n(r,e())[0]}catch(r){console.error(r);return false}}return y(r)}

/**
 * php序列化字符串
 * @param {array|object|string} r
 * @returns {string}
 */
function serialize(r){var e=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(r){return typeof r}:function(r){return r&&typeof Symbol==="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r};var t,n,o;var a="";var i="";var c=0;var f=function r(e){return~-encodeURI(e).split(/%..|./).length};var u=function r(t){var n;var o;var a;var i;var c=typeof t==="undefined"?"undefined":e(t);if(c==="object"&&!t){return"null"}if(c==="object"){if(!t.constructor){return"object"}a=t.constructor.toString();n=a.match(/(\w+)\(/);if(n){a=n[1].toLowerCase()}i=["boolean","number","string","array"];for(o in i){if(a===i[o]){c=i[o];break}}}return c};var b=u(r);switch(b){case"function":t="";break;case"boolean":t="b:"+(r?"1":"0");break;case"number":t=(Math.round(r)===r?"i":"d")+":"+r;break;case"string":t="s:"+f(r)+':"'+r+'"';break;case"array":case"object":t="a";for(n in r){if(r.hasOwnProperty(n)){a=u(r[n]);if(a==="function"){continue}o=n.match(/^[0-9]+$/)?parseInt(n,10):n;i+=serialize(o)+serialize(r[n]);c++}}t+=":"+c+":{"+i+"}";break;case"undefined":default:t="N";break}if(b!=="object"&&b!=="array"){t+=";"}return t}

/**
 * json 编码
 * @param {array|object|string} mixedVal
 * @return {*}
 */
function json_encode (mixedVal) {/* del start */ var $global = (typeof window !== 'undefined' ? window : global); $global.$locutus = $global.$locutus || {}; var $locutus = $global.$locutus; $locutus.php = $locutus.php || {}; var json = $global.JSON; var retVal; /* del end */ try {/* del start */ if (typeof json === 'object' && typeof json.stringify === 'function') {retVal = json.stringify(mixedVal); if (retVal === undefined) {throw new SyntaxError('json_encode'); } return retVal; } /* del end */ var value = mixedVal; var quote = function (string) {var escapeChars = ['\u0000-\u001f', '\u007f-\u009f', '\u00ad', '\u0600-\u0604', '\u070f', '\u17b4', '\u17b5', '\u200c-\u200f', '\u2028-\u202f', '\u2060-\u206f', '\ufeff', '\ufff0-\uffff'].join(''); var escapable = new RegExp('[\\"' + escapeChars + ']', 'g'); var meta = {/*table of character substitutions*/ '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\'}; escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) {var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; }; var _str = function (key, holder) {var gap = ''; var indent = '    '; /* The loop counter.*/ var i = 0; /* The member key.*/ var k = ''; /* The member value.*/ var v = ''; var length = 0; var mind = gap; var partial = []; var value = holder[key]; /* If the value has a toJSON method, call it to obtain a replacement value.*/ if (value && typeof value === 'object' && typeof value.toJSON === 'function') {value = value.toJSON(key); } /* What happens next depends on the value's type.*/ switch (typeof value) {case 'string': return quote(value); case 'number': /* JSON numbers must be finite. Encode non-finite numbers as null.*/ return isFinite(value) ? String(value) : 'null'; case 'boolean': /* If the value is a boolean or null, convert it to a string.*/ return String(value); case 'object': if (!value) {return 'null'; } /* Make an array to hold the partial results of stringifying this object value.*/ gap += indent; partial = []; /* Is the value an array?*/ if (Object.prototype.toString.apply(value) === '[object Array]') {length = value.length; for (i = 0; i < length; i += 1) {partial[i] = _str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']': '[' + partial.join(',') + ']'; /*// gap = mind // not used*/ return v; } /* Iterate through all of the keys in the object.*/ for (k in value) {if (Object.hasOwnProperty.call(value, k)) {v = _str(k, value); if (v) {partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}': '{' + partial.join(',') + '}'; /*// gap = mind // Not used*/ return v; case 'undefined': case 'function': default: throw new SyntaxError('json_encode'); } }; return _str('', {'': value }); } catch (err) {if (!(err instanceof SyntaxError)) {throw new Error('Unexpected error type in json_encode()'); } /* usable by json_last_error()*/ $locutus.php.last_error_json = 4; return null; } }

/**
 * json 字符串解码
 * @param strJson
 * @return {*}
 */
function json_decode (strJson) {/* del start */ var $global = (typeof window !== 'undefined' ? window : global); $global.$locutus = $global.$locutus || {}; var $locutus = $global.$locutus; $locutus.php = $locutus.php || {}; var json = $global.JSON; if (typeof json === 'object' && typeof json.parse === 'function') {try {return json.parse(strJson); } catch (err) {if (!(err instanceof SyntaxError)) {throw new Error('Unexpected error type in json_decode()'); } /* usable by json_last_error()*/ $locutus.php.last_error_json = 4; return null; } } /* del end */ var chars = ['\u0000', '\u00ad', '\u0600-\u0604', '\u070f', '\u17b4', '\u17b5', '\u200c-\u200f', '\u2028-\u202f', '\u2060-\u206f', '\ufeff', '\ufff0-\uffff'].join(''); var cx = new RegExp('[' + chars + ']', 'g'); var j; var text = strJson; cx.lastIndex = 0; if (cx.test(text)) {text = text.replace(cx, function (a) {return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } var m = (/^[\],:{}\s]*$/) .test(text.replace(/\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, '')); if (m) {j = eval('(' + text + ')'); return j; } /*// usable by json_last_error()*/ $locutus.php.last_error_json = 4; return null; }

/**
 * sha1 字符串加密
 * @param {string} r
 * @return {*}
 */
function sha1(r){var a;try{var e=require("crypto");var t=e.createHash("sha1");t.update(r);a=t.digest("hex")}catch(r){a=undefined}if(a!==undefined){return a}var o=function(r,a){var e=r<<a|r>>>32-a;return e};var h=function(r){var a="";var e;var t;for(e=7;e>=0;e--){t=r>>>e*4&15;a+=t.toString(16)}return a};var c;var n,v;var d=new Array(80);var u=1732584193;var s=4023233417;var f=2562383102;var C=271733878;var i=3285377520;var A,p,g,b,k;var l;r=unescape(encodeURIComponent(r));var w=r.length;var y=[];for(n=0;n<w-3;n+=4){v=r.charCodeAt(n)<<24|r.charCodeAt(n+1)<<16|r.charCodeAt(n+2)<<8|r.charCodeAt(n+3);y.push(v)}switch(w%4){case 0:n=2147483648;break;case 1:n=r.charCodeAt(w-1)<<24|8388608;break;case 2:n=r.charCodeAt(w-2)<<24|r.charCodeAt(w-1)<<16|32768;break;case 3:n=r.charCodeAt(w-3)<<24|r.charCodeAt(w-2)<<16|r.charCodeAt(w-1)<<8|128;break}y.push(n);while(y.length%16!==14){y.push(0)}y.push(w>>>29);y.push(w<<3&4294967295);for(c=0;c<y.length;c+=16){for(n=0;n<16;n++){d[n]=y[c+n]}for(n=16;n<=79;n++){d[n]=o(d[n-3]^d[n-8]^d[n-14]^d[n-16],1)}A=u;p=s;g=f;b=C;k=i;for(n=0;n<=19;n++){l=o(A,5)+(p&g|~p&b)+k+d[n]+1518500249&4294967295;k=b;b=g;g=o(p,30);p=A;A=l}for(n=20;n<=39;n++){l=o(A,5)+(p^g^b)+k+d[n]+1859775393&4294967295;k=b;b=g;g=o(p,30);p=A;A=l}for(n=40;n<=59;n++){l=o(A,5)+(p&g|p&b|g&b)+k+d[n]+2400959708&4294967295;k=b;b=g;g=o(p,30);p=A;A=l}for(n=60;n<=79;n++){l=o(A,5)+(p^g^b)+k+d[n]+3395469782&4294967295;k=b;b=g;g=o(p,30);p=A;A=l}u=u+A&4294967295;s=s+p&4294967295;f=f+g&4294967295;C=C+b&4294967295;i=i+k&4294967295}l=h(u)+h(s)+h(f)+h(C)+h(i);return l.toLowerCase()}

function my_encode64(data) {return rtrim(strtr(base64_encode(data), '+/', '-_'), '=');}
function my_decode64(data) {return base64_decode(str_pad(strtr(data, '-_', '+/'), strlen(data) % 4, '=', 'STR_PAD_RIGHT'));}



/**
 * js模拟post表单提交
 * @param {string} url
 * @param {object} params
 * @param {string} target 如:_blank
 * @returns {HTMLElement}
 */
function post(url, params, target) {
    var form = document.createElement("form");
    form.action = url;
    form.method = "post";
    form.style.display = "none";
    form.target = target && typeof target === "string" ? target : "";
    for (var attr in params) {
        var opt = document.createElement("input");
        opt.name = attr;
        opt.value = params[attr];
        form.appendChild(opt);
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
    return form;
}

/**
 * js模拟a标签get请求
 * @param {string} url
 * @param {object} params
 * @param {string} target 如:_blank
 */
function get(url, params, target) {
    var aE = document.createElement("a");
    var queryString = "";
    if (params && typeof params === "object") {
        for (var attr in params) {
            queryString += "&" + attr + "=" + params[attr];
        }
        queryString = "?" + queryString.replace(/^[&]*/i, "");
    }
    aE.href = url + queryString;
    aE.target = target && typeof target === "string" ? target : "";
    aE.style.display = "none";
    document.body.appendChild(aE);
    aE.click();
    document.body.removeChild(aE);
    return aE;
}

/**
 * 获取地址参数
 * @param {string} name
 * @param {string} option 选项值有[get,param]
 * @param {number} num option值为param时才有用，从第几项开始截取，最小值是0
 * @returns {*}
 */
function param(name, option, num) {
    (option) || (option = "get");
    (num) || (num = 0);
    if (option === "get") {
        if (!location.search) {
            location.search = location.href.match(/[?].*/i)[0];
        }
        var arr1 = decodeURIComponent(location.search.replace(/^\?/i, "")).split(/&/i);
        var arr2 = {};
        for (var i = 0, len = arr1.length; i < len; i++) {
            var k_v = arr1[i].split("=");
            arr2[k_v[0]] = arr1[i].replace(new RegExp("^" + k_v[0].replace(/([?.{}*\/\[\]+,\\()<>])/ig, "\\$1") + "=", "i"), "");
        }
        return name ? arr2[name] : arr2;
    }
    if (option === "param" && typeof num === "number" && num >= 0) {
        var trim = function (str, preg) {
            if (preg) {
                preg = new RegExp("(^" + preg + "*|" + preg + "*$)", "ig");
            }
            (preg) || (preg = /(^[\s\t\r\n]*|[\s\t\r\n]*$)/ig);
            return str.replace(preg, "");
        };
        var pathname = trim(decodeURIComponent(location.pathname), "\/");
        var arr1 = pathname.split(/\//);
        if (/([a-z_A-Z_0-9\-]+\.[a-zA-Z0-9]+)/i.test(arr1[0])) {
            arr1.shift();
        }
        var new_arr1 = [];
        for (var i = 0, len = arr1.length; i < len; i++) {
            if (i >= num) {
                new_arr1.push(arr1[i]);
            }
        }
        var arr2 = {};
        for (var i = 0, len = new_arr1.length; i < len; i++) {
            if (i % 2 === 0) {
                arr2[new_arr1[i]] = typeof new_arr1[i + 1] === "undefined" ? null : new_arr1[i + 1];
            }
        }
        return name ? arr2[name] : arr2;
    }
    return false;
}

/**
 * 判断浏览器函数(是否是移动端)
 * @returns {boolean}
 */
function is_mobile() {
    if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
        return true; // 移动端
    } else {
        return false; // PC端
    }
}

/**
 * 判断是否是微信浏览器的函数
 * @returns {boolean}
 */
function is_WeiXin() {
    var ua = navigator.userAgent.toLowerCase();
    if (ua.match(/MicroMessenger/i) == "micromessenger") {
        return true;
    }
    return false;
}

/**
 * 判断是支付宝app的浏览器
 * @returns {boolean}
 */
function is_alipay() {
    var userAgent = navigator.userAgent.toLowerCase();
    if (userAgent.match(/Alipay/i) == "alipay") {
        return true;
    }
    return false;
}

function my_to_url(url, type) {
    (url) || (url = document.referrer);
    (type) || (type = -1);
    if (location.replace && type === -1) {
        location.replace(url);
    } else if (history.replaceState && type === -1) {
        history.replaceState({}, document.title, url);
        /*刷新*/
        location.reload();
    } else {
        location.href = url;
    }
}

/**
 * 字符串替换
 * @param {array|string|RegExp} search_str 模式 search_str
 * @param {array|string} replace_str 替换为 replace_str
 * @param {string} strings 要替换的字符串
 * @param {number} l 替换次数，值为-1的时候为全部替换
 * @returns {string}
 */
function str_replace(search_str, replace_str, strings, l) {
    if (Object.prototype.toString.call(search_str) === "[object Array]") {
        if (Object.prototype.toString.call(replace_str) === "[object Array]" && search_str.length == replace_str.length) {
            for (var i = 0, len = search_str.length; i < len; i++) {
                strings = str_replace(search_str[i], replace_str[i], strings, l);
            }
        }
    } else if (l > 1) {
        for (var i = 0; i < l; i++) {
            strings = str_replace(search_str, replace_str, strings);
        }
    } else {
        if (typeof replace_str === "string" || typeof replace_str === "number") {
            if (Object.prototype.toString.call(search_str) === "[object RegExp]") {
                if (l === -1) {
                    var tag = search_str.global ? "g" : "g";
                    (search_str.ignoreCase) && (tag += "i");
                    (search_str.multiline) && (tag += "m");
                    var reg = new RegExp(search_str.source, tag);
                    //console.log(reg);
                    strings = strings.replace(reg, replace_str);
                } else {
                    (search_str.global) || (strings = strings.replace(search_str, replace_str));
                }
            }
            else {
                if (l === -1) {
                    var reg = new RegExp(search_str.replace(/(\.|\*|\+|\?|\(|\)|\[|\]|\{|\}|\\|\/|\|)/gi, "\\$1"), "g");
                    //console.log(reg);
                    strings = strings.replace(reg, replace_str);
                } else {
                    strings = strings.replace(search_str, replace_str);
                }
            }
        }
    }
    return strings;
}

/**
 * 获取两个时间的时间差,默认时间 t1 > t2，默认返回天数差
 * @param {string|number} t1
 * @param {string|number} t2
 * @param {string} key 选择返回哪种数值（天数差: day|d,小时差：hours|H,分钟差：minute|i）
 * @returns {null}
 */
function diff_between2time(t1, t2, key) {
    var regexp_num = /\d{10}/i;
    var second1, second2, tem, data = {week: null, day: null, hours: null, minute: null, second: null};
    var i_s = 60, h_s = 3600, d_s = 86400, w_s = 3600 * 24 * 7;
    if (is_string(t1) || is_number(t1)) {
        t1 = "" + t1;
        second1 = regexp_num.test(t1) ? parseInt(t1, 10) : strtotime(t1);
    }
    if (is_string(t2) || is_number(t2)) {
        t2 = "" + t2;
        second2 = regexp_num.test(t2) ? parseInt(t2, 10) : strtotime(t2);
    }
    if (second1 < second2) {
        //缓存大的值
        tem = second2;
        second2 = second1;
        second1 = tem;
    }
    //周差
    data.w = data.week = (second1 - second2) % w_s === 0 ? ~~((second1 - second2) / w_s) : ~~((second1 - second2) / w_s) + 1;
    //天数差
    data.d = data.day = (second1 - second2) % 86400 === 0 ? ~~((second1 - second2) / 86400) : ~~((second1 - second2) / 86400) + 1;
    //小时差
    data.H = data.hours = (second1 - second2) % h_s === 0 ? ~~((second1 - second2) / h_s) : ~~((second1 - second2) / h_s) + 1;
    //分钟差
    data.i = data.minute = (second1 - second2) % i_s === 0 ? ~~((second1 - second2) / i_s) : ~~((second1 - second2) / i_s) + 1;
    //秒差
    data.s = data.second = second1 - second2;
    return key ? data[key] : data.day;
}

function set_url_data(obj, lv1, lv2) {
    (lv1) || (lv1 = "&");
    (lv2) || (lv2 = "=");
    var get_str = "";
    if (obj) {
        for (var attr in obj) {
            get_str += attr + lv2 + obj[attr] + lv1;
        }
    }
    return get_str;
}

function my_get_url_data(str, key, clear_key, lv1, lv2) {
    (lv1) || (lv1 = "&");
    (lv2) || (lv2 = "=");
    var arr = str.split(lv1);
    var data = {};
    for (var i = 0, len = arr.length; i < len; i++) {
        var d = arr[i].split(lv2);
        if (d.length > 2) {
            for (var j = 1, j1 = 0, _len = d.length, _d = []; j < _len; j++, j1++) {
                _d[j1] = d[j];
            }
            d[1] = _d.join(lv2);
        }
        data[d[0]] = d[1];
    }
    delete data[""];
    if (clear_key) {
        delete data[clear_key];
    }
    return key ? data[key] : data;
}

/**
 * 获取数组的维度级别
 * @param {array|object} arr
 * @return {number}
 */
function array_level(arr) {
    var al = [0];
    array_level.aL(arr, al);
    return Math.max.apply(al, al);
}
array_level.aL = function (arr, al, level) {
    is_exist(level) || (level = 0);
    if (is_array(arr) || is_object(arr)) {
        level++;
        al.push(level);
        for (var key in arr) {
            array_level.aL(arr[key], al, level);
        }
    }
};

/**
 * 降频操作
 * @param {function} fn
 * @param {number} t
 * @param {string} id_name
 * @param {object} obj
 */
function frequency(fn, t, id_name, obj) {
    if (!is_object(obj)) {
        obj = this;
        is_object(obj.frequency_id) || (obj.frequency_id = {});
        obj = obj.frequency_id;
    }
    (is_number(t) && t > 0) || (t = 300);
    (is_string(id_name) && id_name.length > 0) || (id_name = "idd");
    clearTimeout(obj[id_name]);
    obj[id_name] = setTimeout(function () {
        is_function(fn) && fn.call(obj, t, id_name);
    }, t);
}

/**
 * 获取css样式
 * @param {Element} ele
 * @param {string} attr
 * @returns {string}
 */
function getCSS(ele, attr) {
    return window.getComputedStyle ? getComputedStyle(ele)[attr] : ele.currentStyle[attr];
}

/**
 * 打开新窗口（打开弹窗）
 * @param {string} url 可选。打开指定的页面的URL。如果没有指定URL，打开一个新的空白窗口
 * @param {string} name 可选。指定target属性或窗口的名称
 * @param {object|null} opt
 * @param {boolean} replace
 */
function open_window(url, name, opt, replace) {
    var attr = {
        height: 800,
        width: 1200,
        top: 100,
        left: 100,
        toolbar: "no",
        scrollbars: "no",
        resizable: "no",
        location: "no",
        status: "no",
        menubar: "no",
    };
    if (is_object(opt)) {
        foreach(opt, function (key, value) {
            in_array(key, ["height", "width", "top", "left", "toolbar", "scrollbars", "resizable", "location", "status", "menubar"], true) && (attr[key] = value);
        });
    }
    //设置新窗口的特性
    var features = "";
    foreach(attr, function (key, val) {
        features += "," + key + "=" + val;
    });
    is_exist(name) || (name = "open1");
    window.open(url, name, trim(features, "[ ,]"), replace);
}

/**
 * 定时器
 * @param {function} fn 返回值为 true 时停止定时器
 * @param {number} t 定时器时间间隔，默认1秒间隔，单位毫秒
 * @param {string} name 名称，防止混淆
 */
function setTimeout_timer(fn, t, name) {
    is_object(this.recursion_id) || (this.recursion_id = {});
    var o = this.recursion_id, stop = false, self = this;
    is_exist(name) || (name = "idd");
    is_int(t) || (t = 1000);
    clearTimeout(o[name]);
    o[name] = setTimeout(function () {
        is_function(fn) && (stop = fn.call(o, t, name));
        setTimeout_timer.call(self, fn, t, name);
        if (stop === true) {
            clearTimeout(o[name]);
        }
    }, parseFloat(t));
}

/**
 * 获取存在的值
 * @return {*}
 */
function get_vars() {
    for (var i = 0, len = arguments.length; i < len; i++) {
        if (is_exist(arguments[i])) {
            return arguments[i];
        }
    }
    return false;
}



/**
 * cookie操作
 */
function cookies() {
    if (arguments.length > 0) {
        for (var i = 0, len = arguments.length; i < len; i++) {
            if (typeof arguments[i] === "function") {
                arguments[i].call(this);
            }
            if (typeof arguments[i] === "object" && !("length" in arguments[i])) {
                for (var att in arguments[i]) {
                    this[att] = arguments[i][att];
                }
            }
        }
    }
}

cookies.prototype = {
    /**
     * 设置cookie
     * @param {string} name
     * @param {string} value
     * @param {number|Date} expires 过期时间（单位秒，10位数字。如：~~(new Date().getTime()/1000)+s 。为空的话是Session模式就是浏览器关闭后自动清除）
     * @param {string} path 路径，为空的话默认为‘/’
     * @param {string} domain 所属域名，为空默认是当前页面域名
     * @param secure
     */
    setCookie: function (name, value, expires, path, domain, secure) {
        if (typeof expires === 'string' && (/^\d+$/).test(expires)) {
            expires = parseInt(expires, 10)
        }
        if (expires instanceof Date) {
            expires = expires.toUTCString()
        } else if (typeof expires === 'number') {
            expires = (new Date(expires * 1e3)).toUTCString()
        }
        var r = [name + '=' + urlencode(value)];
        var s = {
            expires: expires,
            path: path,
            domain: domain
        };
        for (var attr in s) {
            if (s.hasOwnProperty(attr)) {
                // Exclude items on Object.prototype
                s[attr] && r.push(attr + '=' + s[attr])
            }
        }
        if (secure) {
            r.push('secure');
        }
        window.document.cookie = r.join(';');
    },
    /**
     * 删除单个cookie
     * @param {string} name
     * @param {string} path
     * @param {string} domain
     * @param secure
     * @return {boolean}
     */
    delCookie: function (name, path, domain, secure) {
        this.setCookie(name, "", 0, path, domain, secure);
        return !this.getCookie(name);
    },
    /**
     * 获取单个cookie
     * @param name
     * @returns {string}
     */
    getCookie: function (name) {
        var arr = document.cookie.split("; ");
        var c_str = "";
        foreach(arr, function (key, value) {
            var a = value.split("=");
            if (a[0] === name) {
                c_str = a[1];
                return 0; //停止for循环
            }
        });
        return urldecode(c_str);
    },
    /**
     * 获取多个cookie值
     */
    getCookieAll: function () {
        var arr = document.cookie.split("; ");
        var data = {};
        foreach(arr, function (key, value) {
            var a = value.split("=");
            data[a[0]] = urldecode(a[1]);
        });
        return data;
    },
    /**
     * 批量删除cookie
     * @param {array} arg
     * @param {string} path
     * @param {string} domain
     * @param secure
     */
    delCookieAll: function (arg, path, domain, secure) {
        if (is_array(arg)) {
            for (var i = 0, len = arg.length; i < len; i++) {
                this.delCookie(arg[i], path, domain, secure);
            }
        } else {
            var arr = document.cookie.split("; ");
            for (var i = 0, len = arr.length; i < len; i++) {
                var a = arr[i].split("=");
                this.delCookie(a[0], path, domain, secure);
            }
        }
    },
    /**
     * 批量设置cookie
     * @param {array|object} data 二维数组
     * @param {number|Date} expires cookie过期时间，单位秒
     * @param {string} path
     * @param {string} domain
     * @param secure
     */
    setCookieAll: function (data, expires, path, domain, secure) {
        if (is_array(data) || is_object(data)) {
            var self = this;
            foreach(data, function (k, v) {
                if (is_object(v)) {
                    v.expires && (expires = v.expires);
                    v.path && (path = v.path);
                    v.domain && (domain = v.domain);
                    v.secure && (secure = v.secure);
                    self.setCookie(v.name, v.value, expires, path, domain, secure);
                }
            });
        }
    },
};

function EventUtil() {
    this.add = function (element, eventType, fn, boolean, event_fn) {
        (boolean) || (boolean = false);
        (event_fn) || (event_fn = "event_fn");
        element[eventType + event_fn] = fn;
        if (element.addEventListener) {
            element.addEventListener(eventType, element[eventType + event_fn], boolean);
        } else if (element.attachEvent) {
            element.attachEvent("on" + eventType, element[eventType + event_fn]);
        } else {
            element["on" + eventType] = fn;
        }
    };
    this.remove = function (element, eventType, boolean, event_fn) {
        (boolean) || (boolean = false);
        (event_fn) || (event_fn = "event_fn");
        if (element.removeEventListener) {
            element.removeEventListener(eventType, element[eventType + event_fn], boolean);
        } else if (element.detachEvent) {
            element.detachEvent("on" + eventType, element[eventType + event_fn]);
        } else {
            element["on" + eventType] = null;
        }
    };
    this.getEvent = function (event) {
        return event ? event : window.event;
    };
    this.getTarget = function (event) {
        return event ? event.target : event.srcElement;
    };
    this.preventDefault = function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    };
    this.stopPropagation = function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }

    }
}

EventUtil.prototype = {
    win: window
};

function search_keyword(config) {
    if (Object.prototype.toString.call(config) === "[object Object]") {
        for (var attr in config) {
            this[attr] = config[attr];
        }
    }
}

search_keyword.prototype = {
    /**
     * 数组截取
     * @param  array array  [description]
     * @param  number start  [description]
     * @param  number length [description]
     * @return array        [description]
     */
    array_slice: function (array, start, length) {
        var arr = [];
        length = length < 0 ? 0 : length;
        for (var i = 0, j = 0, len = array.length; i < len; i++) {
            if (i >= start && i < length + start) {
                arr[j] = array[i];
                j++;
            }
        }
        return arr;
    },
    /**
     * 搜索词分割，左->右，字数由多到少
     * @param  {[type]} length   [description]
     * @param  {[type]} array    [description]
     * @param  {[type]} save_arr [description]
     * @return {[type]}          [description]
     */
    search1: function (length, array, save_arr) {
        for (var i = 0, len = array.length; i < len; i++) {
            (i + length <= len) && (save_arr[save_arr.length] = this.array_slice(array, i, length));
            //(i + length <= len) && (save_arr[save_arr.length] = array.slice(i, length));
        }
    },
    /**
     * 搜索词分割
     * @param  string keyword  [搜索词]
     * @param  boole|number toString [布尔值或者 0，1]
     * @return array          [返回数组]
     */
    keyword: function (keyword, toString) {
        var array = keyword.split('');
        var save_arr = [];
        var l, len;
        len = array.length;
        for (var i = len; i > 0; i--) {
            this.search1(i, array, save_arr);
        }
        if (toString) {
            for (var i = 0, len = save_arr.length; i < len; i++) {
                save_arr[i] = save_arr[i].join("");
            }
        }
        return save_arr;
    },

    set_url_data: function (obj, lv1, lv2) {
        (lv1) || (lv1 = "&");
        (lv2) || (lv2 = "=");
        var get_str = "";
        if (obj) {
            for (var attr in obj) {
                get_str += attr + lv2 + obj[attr] + lv1;
            }
        }
        return get_str;
    },
    /**
     * 删除左右两端的空格
     * @param  {[type]} str  [description]
     * @param  {[type]} preg [description]
     * @return {[type]}      [description]
     */
    trim: function (str, preg) {
        if (preg) {
            preg = new RegExp("(^" + preg + "*|" + preg + "*$)", "ig");
        }
        (preg) || (preg = /(^[\s\t\r\n]*|[\s\t\r\n]*$)/ig);
        return str.replace(preg, "");
    }
};

/**
 * 设置对象属性不可修改，不可删除，不可枚举等
 * @param {Object|Array|function|Storage} obj
 * @param {array|object|string} attrList
 */
function attrNotEach(obj, attrList) {
    var O = {writable: false, configurable: false, enumerable: false}; //设置对象属性不可修改，不可删除，不可枚举
    var list = ["[object Function]", "[object Storage]", "[object Window]"], val;
    if (is_object(obj) || is_array(obj) || in_array(Object.prototype.toString.call(obj), list, true)) {
        if (is_array(attrList)) {
            for (var i = 0, len = attrList.length; i < len; i++) {
                val = attrList[i];
                is_string(val) && Object.defineProperty(obj, val, O);
            }
        } else if (is_object(attrList)) {
            for (var attr in attrList) {
                val = attrList[attr];
                is_string(val) && Object.defineProperty(obj, val, O);
                is_object(val) && Object.defineProperty(obj, attr, Object.assign({}, O, val));
            }
        } else {
            is_string(attrList) && Object.defineProperty(obj, attrList, O);
        }
    }
}

/**
 * 对象属性监听
 * @param {string} key
 * @param {function|object} getFun
 * @param {function} setFun
 */
Object.prototype.attributeListener = function (key, getFun, setFun) {
    if (/^[\S\s]+$/.test(key)) {
        var O = {writable: true, configurable: true, enumerable: false, value: this[key]}, tk = "__tempKey__", temp_key = "temp__" + key, temp;
        if (!is_object(this[tk])) {
            this[tk] = {};
            Object.defineProperty(this, tk, {writable: true, configurable: true, enumerable: false});
        }
        if (is_object(getFun)) {
            temp = getFun;
            temp.writable && (O.writable = temp.writable);
            temp.configurable && (O.configurable = temp.configurable);
            temp.enumerable && (O.enumerable = temp.enumerable);
            temp.value && (O.value = temp.value);
            getFun = temp.get;
            setFun = temp.set;
        }
        var cFn = {
            get: function () {
                is_function(getFun) && getFun.call(this);
                return this[tk][temp_key];
            },
            set: function (newValue) {
                this[tk][temp_key] = newValue;
                is_function(setFun) && setFun.call(this, newValue);
            }
        };
        Object.defineProperty(this, key, O);
        Object.defineProperty(this, key, cFn);
    }
};

/**
 * 获取对象、数组末尾元素
 * @param {Number} index  大于0的整数
 * @returns {*}
 */
Object.prototype.endGet = function (index) {
    var op = Object.prototype,
        type = op.toString.call(this), tf = typeof this,
        len, key_list = [], key,
        is_ok = (this !== null && tf !== "boolean");
    (typeof index !== "number" || index < 1) && (index = 1);
    if (type === "[object Array]") {
        len = this.length - index;
        return this[len];
    } else if (is_ok && (tf === "object" || tf === "function")) {
        for (key in this) {
            op.hasOwnProperty.call(this, key) && key_list.push(key);
        }
        len = key_list.length - index;
        key = key_list[len];
        return this[key];
    }
    return false;
};

function end(data, index) {
    return data !== null && (typeof data === "object" || typeof data === "function") ? data.endGet(index) : false;
}

/**
 * 字符串替换
 * @param {string|RegExp|array|object} search
 * @param {string|function|array|object} replace
 * @param {number} limit 替换次数，小于等于0是全局替换
 * @returns {*}
 */
String.prototype.my_replace = function (search, replace, limit) {
    is_int(limit) || (limit = -1);
    var type = Object.prototype.toString, ot = {array: "[object Array]", object: "[object Object]", regexp: "[object RegExp]"};
    var escape = function (str) {return str.replace(/(\.|\*|\+|\?|\(|\)|\[|\]|\{|\}|\\|\/|\|)/g, "\\$1");};
    var tag = {}, reg = null, is_reg_search, rv = this, is_arr_search, is_obj_search, not_arr_obj_search;
    is_arr_search = type.call(search) === ot.array;
    is_obj_search = type.call(search) === ot.object;
    not_arr_obj_search = (!is_arr_search && !is_obj_search);
    if (is_reg_search = type.call(search) === ot.regexp) {
        tag.g = search.global ? "g" : "";
        tag.i = search.ignoreCase ? "i" : "";
        tag.m = search.multiline ? "m" : "";
        tag.s = search.dotAll ? "s" : "";
        tag.y = search.sticky ? "y" : "";
    }
    if (y_string(search) && limit < 1) {
        reg = new RegExp(escape(search), "g");
        return this.replace(reg, replace);
    } else if (y_string(search) && limit > 0) {
        for (var i = 0; i < limit; i++) {
            rv = rv.replace(search, replace);
        }
        return rv;
    } else if (is_reg_search && not_arr_obj_search && limit < 0) {
        reg = new RegExp(search.source, "g" + tag.i + tag.m + tag.s + tag.y);
        return this.replace(reg, replace);
    } else if (is_reg_search && not_arr_obj_search && limit > 0) {
        reg = new RegExp(search.source, tag.i + tag.m + tag.s + tag.y);
        for (var i = 0; i < limit; i++) {
            rv = rv.replace(reg, replace);
        }
        return rv
    } else if (is_arr_search && type.call(replace) === ot.array) {
        for (var i = 0, len = search.length; i < len; i++) {
            rv = rv.my_replace(search[i], replace[i], limit);
        }
        return rv
    } else if (is_obj_search && type.call(replace) === ot.object) {
        var k = "";
        for (k in search) {
            if (search.hasOwnProperty(k)) {
                rv = rv.my_replace(search[k], replace[k], limit);
            }
        }
        return rv;
    }
    return this;
};

/**
 * 对象或数组转换成元素节点
 * @param {object|array|string} ele_data
 * @param {Element|object|array} container_ele
 * @returns {*}
 * @constructor
 */
function OA2Element(ele_data, container_ele) {
    if (is_object(ele_data)) {
        var tagName = ele_data.tagName, attr = ele_data.attr, child = ele_data.child;
        if (y_string(tagName)) {
            var E = document.createElement(tagName), k;
            for (k in ele_data) {
                if (ele_data.hasOwnProperty(k)) {
                    E[k] = ele_data[k];
                }
            }
            if (is_object(attr)) {
                for (var k1 in attr) {
                    if (attr.hasOwnProperty(k1) && y_string(attr[k1])) {
                        E.setAttribute(k1, attr[k1]);
                    }
                }
            } else if (is_array(attr)) {
                attr.foreach(function (k, v) {
                    if (is_object(v) && y_string(v.name) && y_string(v.value)) {
                        E.setAttribute(v.name, v.value);
                    } else if (is_array(v) && y_string(v[0]) && y_string(v[1])) {
                        E.setAttribute(v[0], v[1]);
                    }
                });
            }
            if (is_array(child)) {
                var Fragment = document.createDocumentFragment();
                child.foreach(function (index, v) {
                    Fragment.appendChild(OA2Element(v));
                    //Fragment.insertBefore()
                });
                E.appendChild(Fragment);
            }
            is_element(container_ele) && container_ele.appendChild(E);
            return E;
        }
    } else if (is_array(ele_data, 1)) {
        var Fragment = document.createDocumentFragment();
        ele_data.foreach(function (k, v) {
            Fragment.appendChild(OA2Element(v));
        });
        is_element(container_ele) && container_ele.appendChild(Fragment);
        return Fragment;
    } else {
        if (y_string(ele_data)) {
            var oE = {tagName: ele_data}, v3;
            for (var i = 1, len = arguments.length - 1; i < len; i++) {
                v3 = arguments[i];
                if (is_object(v3)) {
                    set_obj_attr(oE, v3);
                } else if (is_array(v3)) {
                    y_string(v3[0]) && (oE[v3[0]] = v3[1]);
                }
            }
            return OA2Element(oE, arguments[len]);
        }
    }
    return false;
}

/**
 * 模板字符串替换
 * @param {object|array} data
 * @param {string} tpl_string
 * @param {string|RegExp} mode_start
 * @param {string|RegExp} mode_end
 * @returns {*}
 */
function tpl_data_replace(data, tpl_string, mode_start, mode_end) {
    var escape=function(str){return str.replace(/([{}\[\]().+*?^$|\/])/g,"\\$1");}, type=Object.prototype.toString, rvFn=function(rv){is_array(rv)&&(rv="Array");is_object(rv)&&(rv="Object");is_function(rv)&&(rv="Function");return rv;};
    var get_obj_val = function (obj, str) {
        if (is_object(obj)) {
            if (is_array(str)) {
                for (var i = 0, len = str.length, attr, end_len = len - 1, rv; i < len; i++) {
                    attr = str[i];
                    rv = obj[attr];
                    if (is_object(rv) || is_array(rv, 1)) {
                        obj = obj[attr];
                        if (i === end_len) {
                            return rvFn(rv);
                        }
                    } else {
                        return rvFn(rv);
                    }
                }
            } else if (y_string(str)) {
                str = str.replace(/(^[.]+|[.]+$)/g, "");
                var list = str.split(/[.]+/);
                return get_obj_val(obj, list);
            }
        }
        return false;
    };
    var is_reg = "[object RegExp]", is_reg_mode_start = (type.call(mode_start) === is_reg), is_reg_mode_end = (type.call(mode_end) === is_reg);
    if (is_reg_mode_start || mode_start === 0) {
        (mode_start === 0) && (mode_start = /(@[A-Za-z0-9._\-]+@)/g);
        if (is_object(data) && y_string(tpl_string)) {
            is_reg_mode_end || (mode_end = /([A-Za-z0-9._\-])+/g);
            return tpl_string.replace(mode_start, function (a) {
                var _a = a.match(mode_end);
                return get_obj_val(data, _a[0]);
            });
        }
    } else {
        y_string(mode_start) || (mode_start = "@");
        y_string(mode_end) || (mode_end = "@");
        if (is_object(data)) {
            var k, v, r_arr = [];
            for (k in data) {
                v = data[k];
                if (data.hasOwnProperty(k)) {
                    r_arr.push(escape(mode_start + k + mode_end));
                }
            }
            if (y_string(tpl_string)) {
                var r_str = r_arr.join("|");
                var reg3 = new RegExp("(" + r_str + ")", "g");
                return tpl_string.replace(reg3, function (a) {
                    var _a = a.replace(new RegExp("(^" + escape(mode_start) + "|" + escape(mode_end) + "$)", "g"), "");
                    return rvFn(data[_a]);
                });
            }
        }
    }
    return false;
}

/**
 * 简单的模板引擎
 * @param {string|Element} tpl
 * @param {string} start 开始标记
 * @param {string} end 结束标记
 * @returns {Function}
 */
function my_template(tpl, start, end) {
    is_element(tpl) && (tpl = tpl.innerHTML);
    var match, rv, fn, str = '';
    var reg = {
        start: y_string(start) ? start : "<@",
        end: y_string(end) ? end : "@>",
        re: {
            start: /(\{.*?\})/g,
            end: /([A-Za-z0-9._\-]+)/g
        },
    };
    var regStr = {
        jsCode: tpl_data_replace(reg, "({@start}.*?{@end})", reg.re.start, reg.re.end),
        getJsCode: tpl_data_replace(reg, "(^\s*{@start}[=]*|{@end}\s*$)", reg.re.start, reg.re.end),
    };
    //构成函数里面的代码
    var fnCode = ['var args = arguments;\nvar r=[];\n'],
        jsCodeReg = new RegExp(regStr.jsCode, "g");
    //辅助添加代码片段
    var add = function (str, opt) {
        opt || (opt = 1);
        var _str = str;
        str = str.replace(/(\n)/g, "☗n☖").replace(/(\r)/g, "☗r☖").replace(/(\t)/g, "☗t☖").replace(/(['"])/g, "\\$1");
        (opt === 1) && fnCode.push("r.push('" + str + "');\n ");
        (opt === 2) && fnCode.push("r.push(" + _str + ");\n ");
    };
    //用于清除条两边标签，获取纯的js代码片段
    var reg_trim_tag = new RegExp(regStr.getJsCode, "g");
    //用于清除js代码片段部分
    var reg_del_js = new RegExp(jsCodeReg.source, "g");
    //用于存储上一次匹配到的位置
    var ma = {index: 0};
    while (match = jsCodeReg.exec(tpl)) {
        str = tpl.slice(ma.index, ma.index = match.index);
        str = str.replace(reg_del_js, "");
        add(str);
        if (String(match[1]).search(reg.start + "=") !== -1) {
            add(match[1].replace(reg_trim_tag, ""), 2);
        } else {
            fnCode.push(String(match[1]).replace(reg_trim_tag, "") + "\n ");
        }
        //console.log(str, match);
    }
    str = tpl.slice(ma.index, tpl.length);
    str = str.replace(new RegExp(jsCodeReg.source, "g"), "");
    add(str);
    fnCode.push("return r.join('').replace(/(☗n☖)/g,'\\n').replace(/(☗r☖)/g,'\\r').replace(/(☗t☖)/g,'\\t');");
    rv = fnCode.join('');
    fn = new Function("data", "arg2", "arg3", rv);
    //console.log(fn);
    return fn;
}

/**
 * 重构二维数组
 * @param {array|object} lv2_arr
 * @param {string} field
 * @returns {boolean|object}
 */
function lv2_reconfig(lv2_arr, field) {
    var temp = false;
    if ((is_object(lv2_arr) || is_array(lv2_arr)) && y_string(field)) {
        temp = {};
        lv2_arr.foreach(function (k, v) {
            if (is_object(v) && y_string(v[field])) {
                temp[v[field]] = v;
            }
        });
    }
    return temp;
}

/**
 * 获取树的路径
 * @param {array|object} lv2_data
 * @param {number} id
 * @param {string} id_field
 * @param {string} pid_field
 * @param {number} index
 * @returns {Array}
 */
function get_tree_path(lv2_data, id, id_field, pid_field, index) {
    y_string(id_field) || (id_field = "id");
    y_string(pid_field) || (pid_field = "pid");
    y_string(id) || (id = 0);
    y_string(index) || (index = 10);
    var temp = {}, pid = -1, list = [];
    temp = lv2_reconfig(lv2_data, id_field);
    id = temp[id][id_field];
    pid = temp[id][pid_field];
    //先把当前的子元素添加入数组
    id && list.push(temp[id]);
    for (var i = 0; i < index; i++) {
        if (pid && pid > 0 && temp[pid]) {
            list.push(temp[pid]);
        } else {
            break;
        }
        pid = temp[pid][pid_field];
    }
    return list.reverse();
}

/**
 * 给多级列表添加字段 block 区块，用与记录下级跟上级之间的关系
 * @param {array|object} lv2_data
 * @param {string} id_field
 * @param {string} pid_field
 * @param {boolean|null|undefined} is_reconfig 是否重构数据
 * @param {number} r_max 最大递归次数，防止内存溢出奔溃(也可以当做处理多级列表最大级别)
 * @param {number} r 当前递归次数
 * @returns {object}
 */
function set_tree_block(lv2_data, id_field, pid_field, is_reconfig, r_max, r) {
    var temp = {}, k, v, pid, id;
    y_string(id_field) || (id_field = "id");
    y_string(pid_field) || (pid_field = "pid");
    (!y_string(r) || !is_number(r)) && (r = 1);
    (!y_string(r_max) || !is_number(r_max)) && (r_max = 10);
    is_exist(is_reconfig, [0,"", null, undefined]) || (is_reconfig = true);
    if (is_reconfig === true) {
        temp = lv2_reconfig(lv2_data, id_field);
    } else {
        temp = lv2_data;
    }
    for (k in temp) {
        v = temp[k];
        id = v[id_field];
        pid = v[pid_field];
        if (pid == 0) {
            temp[k]['block'] = "0,";
        } else if (pid > 0 && temp[pid] && temp[pid]['block']) {
            temp[k]['block'] || (temp[k]['block'] = temp[pid]['block'] + temp[pid][id_field] + ",");
        }
    }
    if (r <= r_max) {
        return set_tree_block(temp, id_field, pid_field, false, r_max, r + 1);
    }
    return temp;
}

/**
 * 二维数组数据筛选
 * @param {array|object} lv2_arr
 * @param {string|function} field
 * @param {string} opt
 * @param {string} val
 * @param {string|array} name
 * @param {boolean} stop
 * @return {*}
 */
function lv2_query(lv2_arr, field, opt, val, name, stop) {
    var re_data = {lv2: [], lv1: {}, field: []}, reg, v;
    if (is_array(lv2_arr) || is_object(lv2_arr)) {
        for (var i = 0, len = lv2_arr.length; i < len; i++) {
            v = lv2_arr[i];
            if (is_exist(field) && is_exist(val) && in_array(opt, ["=", "=="]) && !is_function(field)) {
                if (val == v[field]) {
                    re_data.lv2.push(v);
                    y_string(name) && re_data.field.push(v[name]);
                    re_data.lv1 = v;
                    if (stop) {
                        return re_data.lv1;
                    }
                }
            } else if (is_exist(field) && is_exist(val) && String(opt).toLocaleLowerCase() === "regexp" && !is_function(field)) {
                reg = new RegExp(val, "i");
                if (reg.test(v[field])) {
                    re_data.lv2.push(v);
                    y_string(name) && re_data.field.push(v[name]);
                    re_data.lv1 = v;
                    if (stop) {
                        return re_data.lv1;
                    }
                }
            } else if (is_exist(field) && is_function(field)) {
                if (in_array(field.call(lv2_arr, i, v, lv2_arr), [true, 1, "1"], true)) {
                    re_data.lv2.push(v);
                    y_string(name) && re_data.field.push(v[name]);
                    re_data.lv1 = v;
                    if (stop) {
                        return re_data.lv1;
                    }
                }
            }
        }
        if (y_string(name)) {
            return re_data.field;
        } else if (is_array(name)) {
            name = name[0];
            return in_array(name, ['lv2', 'lv1', 'field']) ? re_data[name] : re_data;
        } else {
            return re_data.lv2;
        }
    }
    return false;
}

/**
 * 获取对象的键名
 * @param {Object|Array|String|Number} obj
 * @param {number} opt 默认返回自有可枚举属性，值为-1时返回所有自有属性，值为1时返回所有可枚举属性
 * @return {boolean|Array}
 */
function getKeys(obj, opt) {
    var op = Object.prototype, type = op.toString.call(obj), S = "[object String]", N = "[object Number]", key, key_list = [];
    if ((obj !== null && obj !== undefined && typeof obj !== "boolean" && typeof obj === "object") || type === "[object Function]" || type === S || type === N) {
        (type === S || type === N) && (obj = String(obj).split(""));
        if (opt === -1) {
            return Object.getOwnPropertyNames(obj);
        }
        for (key in obj) {
            if (opt) {
                key_list.push(key);
            } else {
                op.hasOwnProperty.call(obj, key) && key_list.push(key);
            }
        }
        return key_list;
    }
    return false;
}

/**
 * 随机打乱顺序
 * @param {Object|Array|string|number} data
 * @param {boolean|number} opt 值为1是保持原先的键值关系
 * @return {*}
 */
function shuffle(data, opt) {
    var exp = ["^\\[object\\s(", "Object|Array|String|Number", ")\\]$"], op = Object.prototype, type = op.toString.call(data), reg, reg_str, key_list;
    reg = new RegExp(exp.join(""), "i"), exp[1] = "String|Number", reg_str = new RegExp(exp.join(""), "i");
    if (!reg.test(type)) {
        return data;
    }
    reg_str.test(type) && (data = String(data).split(""));
    key_list = getKeys(data);
    var len = key_list.length, i, index, temp, _index, result, key;
    for (i = 0; i < len - 1; i++) {
        //随机下标
        index = ~~(Math.random() * (len - i));
        //临时缓存数据
        temp = key_list[index];
        //交换位置
        _index = len - 1 - i;
        key_list[index] = key_list[_index];
        key_list[_index] = temp;
    }
    for (i = 0; i < len; i++) {
        key = key_list[i];
        if (type === "[object Array]") {
            result || (result = []);
            opt ? result[key] = data[key] : result.push(data[key]);
        } else if (type === "[object Object]") {
            result || (result = {});
            opt ? result[key] = data[key] : result[i] = data[key];
        } else {
            result || (result = []);
            opt ? result[key] = data[key] : result.push(data[key]);
        }
    }
    reg_str.test(type) && (result = result.join(""));
    return result;
}

/**
 * 以文本方式读取文件内容
 * @param file
 * @param {function} success_fn
 * @param {function} error_fn
 * @param {string} charset
 */
function file_read_text(file, success_fn, error_fn, charset) {
    if (is_file(file)) {
        var reader = new FileReader();
        reader.readAsText(file, charset);
        reader.onload = function (e) {
            is_function(success_fn) && success_fn.call(reader, file, reader.result, e);
        };
        reader.onerror = function (e) {
            is_function(error_fn) && error_fn.call(reader, file, e);
        };
    }
}

/**
 * 以数据地址方式读取文件内容
 * @param file
 * @param {function} success_fn
 * @param {function} error_fn
 */
function file_read_data_url(file, success_fn, error_fn) {
    if (is_file(file)) {
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function (e) {
            is_function(success_fn) && success_fn.call(reader, file, reader.result, e);
        };
        reader.onerror = function (e) {
            is_function(error_fn) && error_fn.call(reader, file, e);
        };
    }
}

/**
 * 字符串转义
 * @param str
 * @param {number|string|{html:1,regexp:2}} op
 * @param {number} mode
 * @returns {*}
 */
function str_escape(str, op, mode) {
    op || (op = 1);
    if (y_string(str)) {
        if (op === 1 || op === "html") {
            return str = String(str).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), (mode === 2) && (str = str.replace(/'/g, "&#039;").replace(/"/g, "&quot;")), str;
        }
        if (op === 2 || op === "regexp") {
            return str = String(str).replace(/([{}\[\]().*+\/|?\-^$\\])/g, "\\$1"), str;
        }
    } else if (is_object(str) || is_array(str)) {
        for (var k in str) {
            ({}).hasOwnProperty.call(str, k) && (str[k] = str_escape(str[k], op, mode));
        }
        return str;
    }
    return str;
}

/**
 * 还原转义的字符串
 * @param de_str
 * @param {number|string|{html:1,regexp:2}} op
 * @param {number} mode
 * @returns {*}
 */
function de_str_escape(de_str, op, mode) {
    op || (op = 1);
    if (y_string(de_str)) {
        if (op === 1 || op === "html") {
            return de_str = String(de_str).replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">"), (mode === 2) && (de_str.replace(/&#039;/g, "'").replace(/&quot;/g, "\"")), de_str;
        }
        if (op === 2 || op === "regexp") {
            return de_str = String(de_str).replace(/(\\[{}\[\]().*+\/|?\-^$\\])/g, function (match) {
                return match !== "\\" ? match.replace("\\", "") : match.replace("\\\\", "\\");
            }), de_str;
        }
    } else if (is_object(de_str) || is_array(de_str)) {
        for (var k in de_str) {
            ({}).hasOwnProperty.call(de_str, k) && (de_str[k] = de_str_escape(de_str[k], op, mode));
        }
        return de_str;
    }
    return de_str;
}

/**
 * 获取元素路径或者(就近原则)搜索路径中匹配条件的元素
 * @param ele
 * @param rootE
 * @param {string} attr
 * @param {string} opt
 * @param val
 * @returns {*}
 */
function ele_path(ele, rootE, attr, opt, val) {
    var rE = document.documentElement || document.body, path = [], pE, i, len;
    var parent = function (E) {
        return E.parentElement || E.parentNode;
    };
    is_exist(rootE) || (rootE = rE);
    if (is_element(ele)) {
        path.push(ele);
        pE = parent(ele);
        if (is_element(rootE)) {
            while (pE && pE !== document) {
                path.push(pE);
                if (pE === rootE) {
                    break;
                }
                pE = parent(pE);
            }
        }
        if (is_number(rootE)) {
            for (i = 0; i < rootE; i++) {
                path.push(pE);
                if (pE === rE) {
                    break;
                }
                pE = parent(pE);
            }
        }
        //搜索部分
        var is_str_attr = y_string(attr), is_str_val = y_string(val), is_str_opt = y_string(opt), is_ok_val = is_exist(val), is_arr_val = is_array(val, 1), el, el_v, reg;
        if (is_str_attr) {
            for (i = 0, len = path.length; i < len; i++) {
                el = path[i];
                el_v = get_vars(el.getAttribute(attr), el[attr]);
                if (is_str_attr && in_array(opt, ["=", "=="]) && is_str_val && el_v == val) {
                    return el;
                } else if (is_str_attr && is_str_opt && opt.toLowerCase() === "in" && is_arr_val && in_array(el_v, val, true)) {
                    return el;
                } else if (is_str_attr && is_str_val && is_str_opt && opt.toLowerCase() === "regexp") {
                    reg = new RegExp(val, "i");
                    if (y_string(el_v) && reg.test(el_v)) {
                        return el;
                    }
                } else if (is_str_attr && is_str_val && opt === "^=") {
                    //开头匹配
                    reg = new RegExp("^" + val, "i");
                    if (y_string(el_v) && reg.test(el_v)) {
                        return el;
                    }
                } else if (is_str_attr && is_str_val && opt === "$=") {
                    //结尾匹配
                    reg = new RegExp(val + "$", "i");
                    if (y_string(el_v) && reg.test(el_v)) {
                        return el;
                    }
                } else if (is_str_attr && is_str_val && opt === "*=") {
                    //包含
                    reg = new RegExp(val, "i");
                    if (y_string(el_v) && reg.test(el_v)) {
                        return el;
                    }
                }
            }
            return false;
        }
    }
    return path.reverse();
}

/**
 * 获取选中的文本内容
 * @returns {*}
 */
function selected_text() {
    if (window.getSelection) {
        //var gs = getSelection();
        //return gs.baseNode.textContent.substring(gs.baseOffset, gs.focusOffset);
        return getSelection().toString();
    } else if (document.selection) {
        return document.selection.createRange().text;
    }
    return "";
}

/**
 * 文字转语音播放
 * @param {string} text
 * @param {string} lang 语言种类
 * @param {number} volume 声音音量
 * @param {number} rate 语速，数值，默认值是1，范围是0.1到10
 * @param {number} pitch 表示说话的音高，数值，范围从0（最小）到2（最大）。默认值为1
 * @param {SpeechSynthesisVoice} voice  设置说话的声音，在‘speechSynthesis.getVoices()’获取的列表选择
 * @returns {SpeechSynthesisUtterance}
 */
function speak(text, lang, volume, rate, pitch, voice) {
    var msg = new SpeechSynthesisUtterance();
    y_string(lang) || (lang = "zh");
    is_number(volume) || (volume = 50);
    is_number(rate) || (rate = 1);
    is_number(pitch) || (pitch = 1);
    (voice instanceof SpeechSynthesisVoice) || (voice = null);

    msg.text = text;
    msg.lang = lang;
    msg.volume = volume;
    msg.rate = rate;
    msg.pitch = pitch;
    msg.voice = voice;
    speechSynthesis.speak(msg);
    return msg;
}

/**
 * Symbol 相关封装
 * @constructor
 */
function Sym() {
    for (var i = 0, len = arguments.length; i < len; i++) {
        is_function(arguments[i]) && arguments[i].call(this);
    }
    this.__temp__ = {local: {}, global: {}};
    this.lGET = function (key) {
        return this.localGet(key);
    };
    this.gGET = function (key) {
        return this.globalGet(key);
    };
    this.lSET = function (key, value) {
        return this.localSet(key, value);
    };
    this.gSET = function (key, value) {
        return this.globalSet(key, value);
    };
}

Sym.prototype = {
    /**
     * 设置Symbol值
     * @param {Array|Object|String} key
     * @param {Symbol|String|*} value
     * @param {boolean} is_global
     * @return {Sym}
     */
    set: function (key, value, is_global) {
        var k, v, g = this.__temp__.global, lo = this.__temp__.local;
        if (is_array(key) || is_object(key)) {
            for (k in key) {
                this.set(k, key[k], is_global);
            }
        } else {
            if (!is_symbol(key) && this.is_string(key)) {
                if (is_symbol(value)) {
                    this.is_global(value) ? g[key] = value : lo[key] = value;
                } else if (this.is_string(value)) {
                    is_global ? g[value] = Symbol.for(value) : lo[value] = Symbol(value);
                } else {
                    is_global ? g[key] = Symbol.for(key) : lo[key] = Symbol(key);
                }
            }
        }
        return this;
    },
    /**
     * 获取 Symbol
     * @param {String|null} key
     * @param {boolean} is_global
     * @return {*}
     */
    get: function (key, is_global) {
        var g = this.__temp__.global, lo = this.__temp__.local;
        if (this.is_string(key)) {
            return is_global ? g[key] : lo[key];
        }
        return is_global ? g : lo;
    },
    localGet: function (key) {
        return this.get(key, false);
    },
    localSet: function (key, value) {
        return this.set(key, value, false);
    },
    globalGet: function (key) {
        return this.get(key, true);
    },
    globalSet: function (key, value) {
        return this.set(key, value, true);
    },
    is_string: function (arg) {
        return is_exist(arg) && (is_string(arg) || is_float(arg));
    },
    /**
     * 判断Symbol是否是全局的
     * @param {Symbol} arg
     * @return {boolean}
     */
    is_global:function (arg) {
        return is_symbol(arg) && !!Symbol.keyFor(arg);
    }
};

(function () {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function (callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function () {
                    callback(currTime + timeToCall);
                },
                timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function (id) {
            clearTimeout(id);
        };

    //设置对象属性不可修改，不可删除，不可枚举
    var O = {writable: false, configurable: false, enumerable: false};
    Object.defineProperty(array_level, "aL", O);
    attrNotEach(Object.prototype, ["foreach", "foreachAll", "attributeListener", "endGet"]);
    attrNotEach(String.prototype, ["my_replace"]);
    attrNotEach(Sym.prototype, ["get", "set", "localGet", "localSet", "globalGet", "globalSet", "is_string", "is_global"]);
    var fn_list = ["is_array", "is_object", "is_function", "is_string", "is_boolean", "is_number", "is_undefined", "is_null", "is_exist", "is_int", "is_float", "is_element", "is_symbol", "is_file", "y_string", "in_array", "array_level", "get_vars", "attrNotEach", "getKeys", "shuffle", "end"];
    var global = this;
    fn_list.foreach(function (k, v) {
        Object.defineProperty(global, v, {writable: false});
    });
}());
try {
    var LO = new storage();
    var SE = new storage("sessionStorage");
    var CO = new cookies();
    var Events = new EventUtil();
    var sy = new Sym();
} catch (e) {

}

